diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..df4ad4d9 --- /dev/null +++ b/.babelrc @@ -0,0 +1,7 @@ +{ + "presets": ["env"], + "plugins": [ + "add-module-exports", + "transform-es2015-modules-umd" + ] +} diff --git a/.bithoundrc b/.bithoundrc new file mode 100644 index 00000000..46722b1d --- /dev/null +++ b/.bithoundrc @@ -0,0 +1,19 @@ +{ + "ignore": [ + "**/.vscode/**", + "**/node_modules/**", + "**/dist/**", + "**/examples/**" + ], + "test": [ + "**/test/**" + ], + "critics": { + "lint": { + "engine": "eslint" + }, + "wc": { + "limit": 1000 + } + } +} diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..8b1709b6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = LF +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..ac117e1a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,39 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es6": true, + "node": true + }, + "globals": { + "expect": true, + "it": true, + "describe": true, + "beforeEach": true, + "afterEach": true, + "document": false, + "navigator": false, + "window": false + }, + "parser": "babel-eslint", + "extends": "airbnb-base", + "rules": { + "class-methods-use-this": 0, + "no-plusplus": 0, + "arrow-parens": 0, + "no-console": 0, + "import/prefer-default-export": 0, + "comma-dangle": 0, + "no-underscore-dangle": 0, + "no-param-reassign": 0, + "no-return-assign": 0, + "no-restricted-globals": 0, + "no-multi-assign": 0, + "prefer-destructuring": ["error", {"object": true, "array": false}], + "padded-blocks": 0, + "no-sparse-arrays": 0, + "array-bracket-spacing": 0, + "import/no-named-as-default": 0, + "implicit-arrow-linebreak": 0 + } +} diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 00000000..d33152ab --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "javascript-ds-algorithms-book" + } +} diff --git a/.gitignore b/.gitignore index 2458e8b0..0c2aa12a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,10 @@ *.log node_modules coverage +.nyc_output +coverage.lcov +mochawesome-report/* +dist/js/* +dist-/* +dist/ts/* +snippet.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..7def9b91 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: node_js +node_js: + - node +before_script: + - npm install -g --silent firebase-tools +install: + - npm install +script: + - npm run go +after_success: + - npm run coverage + - test $TRAVIS_BRANCH = "master" && test $TRAVIS_PULL_REQUEST = "false" && firebase deploy --token $FIREBASE_TOKEN --non-interactive +notifications: + email: + on_failure: change + on_success: change diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..8b53d61d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,50 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Chrome", + "url": "http://127.0.0.1:8887/examples", + "webRoot": "${workspaceRoot}" + }, + { + "type": "node", + "request": "launch", + "name": "Mocha JS", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "tdd", + "--timeout", + "999999", + "--compilers", + "js:babel-core/register", + "--colors", + "${workspaceRoot}/test/js/**/*.spec.js" + ], + "internalConsoleOptions": "openOnSessionStart" + }, + { + "type": "node", + "request": "launch", + "name": "Mocha TS", + "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", + "args": [ + "-u", + "tdd", + "--timeout", + "999999", + "-r", + "ts-node/register", + "--colors", + "${workspaceRoot}/test/ts/**/**/*.spec.ts" + ], + "protocol": "auto", + "internalConsoleOptions": "openOnSessionStart" + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..55712c19 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "node_modules/typescript/lib" +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..9b4e4d2c --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,23 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "go", + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "type": "npm", + "script": "dev", + "group": { + "kind": "test", + "isDefault": true + } + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..ade741a9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Change Log +All notable changes to the "javascript-datastructures-algorithms" third edition source code bundle will be documented in this file. + +Based on [Keep a Changelog](http://keepachangelog.com/). + +## [Unreleased] +- Initial release diff --git a/README.md b/README.md index 64771d99..96845564 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,89 @@ Learning JavaScript Data Structures and Algorithms ==================================== -Source code of **Learning JavaScript Data Structures and Algorithms** book. +[![Build Status](https://travis-ci.org/loiane/javascript-datastructures-algorithms.svg?branch=master)](https://travis-ci.org/loiane/javascript-datastructures-algorithms) +[![codecov](https://codecov.io/gh/loiane/javascript-datastructures-algorithms/branch/master/graph/badge.svg)](https://codecov.io/gh/loiane/javascript-datastructures-algorithms) +[![devDependencies Status](https://david-dm.org/loiane/javascript-datastructures-algorithms/dev-status.svg)](https://david-dm.org/loiane/javascript-datastructures-algorithms?type=dev) +[![dependencies Status](https://david-dm.org/loiane/javascript-datastructures-algorithms/status.svg)](https://david-dm.org/loiane/javascript-datastructures-algorithms) +[![Greenkeeper badge](https://badges.greenkeeper.io/loiane/javascript-datastructures-algorithms.svg)](https://greenkeeper.io/) -| 1st edition | 2nd edition | -| ------------- |:-------------:| -| ![1st edition](https://d1ldz4te4covpm.cloudfront.net/sites/default/files/imagecache/ppv4_main_book_cover/4874OS_Learning%20JavaScript%20Data%20Structures%20and%20Algorithms.jpg) | ![2nd edition](https://d255esdrn735hr.cloudfront.net/sites/default/files/imagecache/ppv4_main_book_cover/5493OS_5348_Learning%20JavaScript%20Data%20Structures%20and%20Algorithms,%20Second%20Edition.jpg) | -| [Book link](http://amzn.to/1Y1OWPx)| [Book link](http://amzn.to/1TSkcA1)| + +Source code of **Learning JavaScript Data Structures and Algorithms** book, third edition. + +## List of available chapters: + +* 01: [JavaScript: a quick overview](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter01_02) +* 02: [ECMAScript and TypeScript Introduction](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter01_02) +* 03: [Arrays](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter03) +* 04: [Stacks](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter04) +* 05: [Queues and Deques](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter05) +* 06: [LinkedLists](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter06) +* 07: [Sets](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter07) +* 08: [Dictionaries and Hashes](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter08) +* 09: [Recursion](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter09) +* 10: [Trees](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter10) +* 11: [Heap](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter11) +* 12: [Graphs](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter12) +* 13: [Sorting and Searching Algorithms](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter13) +* 14: [Algorithm Design and Techniques](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter14) +* 15: [Algorithm Complexity](https://github.com/loiane/javascript-datastructures-algorithms/tree/third-edition/examples/chapter15) + +### Third Edition Updates + +* Algorithms using ES2015+ (ES6+) +* New data structures and algorithms +* All chapters rewritten and reviewed +* Three (3) new chapters +* Creation of a Data Structures and Algorithms library that can be used in the browser or with Node.js +* Algorithms tested with Mocha + Chai (test code available in `test` directory) +* **TypeScript** version of the source code included (library and tests) + +## Project Structure + +`src/js/index.js` file contains all the data structures and algorithms listed by chapter. + +``` +|_examples (how to use each data structure and algorithm, organized by chapter) +|_src +|___js (source code: JavaScript version) +|_____data-structures +|_______models (classes used by DS: Node, ValuePair, ...) +|_____others (other algorithms such as palindome checker, hanoi tower) +|___ts (source code: TypeScript version) +|_____data-structures +|_______models +|_____others +|_test (unit tests with Mocha and Chai for src) +|___js (tests for JavaScript code) +|___ts (tests for TypeScript code) +``` + +## Installing and running the book examples With Node + +* Install [Node](https://nodejs.org) +* Open terminal/cmd and change directory to this project folder: `cd /Users/.../javascript-datastructures-algorithms` (Linux/Max) or `cd C:/.../javascript-datastructures-algorithms` +* run `npm install` to install all dependencies +* To see the examples, run `http-server html` or `npm run serve`. Open your browser `http:\\localhost:8080` to see the book examples +* Or `cd html/chapter01` and run each javascript file with node: `node 02-Variables` + +## Running the examples in the browser + +* Right click on the html file you would like to see the examples, right click and 'Open with Chrome (or any other browser)' + +* Or open the `examples/index.html` file to easily navigate through all examples: + +* Demo: [https://javascript-ds-algorithms-book.firebaseapp.com](https://javascript-ds-algorithms-book.firebaseapp.com) + + + +Happy Coding! + +## Other editions + +| 1st edition | 2nd edition | 3rd edition | +| ------------- |:-------------:|:-------------:| +| ![1st edition](https://images-na.ssl-images-amazon.com/images/I/51xXGv7QlBL._SX403_BO1,204,203,200_.jpg) | ![2nd edition](https://images-na.ssl-images-amazon.com/images/I/51PWJ%2BoKc2L._SX403_BO1,204,203,200_.jpg) | ![3rd edition](https://images-na.ssl-images-amazon.com/images/I/41oSXp3VztL._SX404_BO1,204,203,200_.jpg) | +| [Book link](http://amzn.to/1Y1OWPx)| [Book link](http://amzn.to/1TSkcA1)| [Book link](http://a.co/cbMlYmJ)| Book link - first edition: - [Packt](https://www.packtpub.com/application-development/learning-javascript-data-structures-and-algorithms) @@ -17,26 +94,14 @@ Book link - first edition: Book link - second edition: - [Packt](https://www.packtpub.com/web-development/learning-javascript-data-structures-and-algorithms-second-edition) - [Amazon](http://amzn.to/1TSkcA1) + - [Chinese version](http://www.ituring.com.cn/book/2029) - [Brazilian Portuguese version](https://novatec.com.br/livros/estruturas-de-dados-algoritmos-em-javascript/) -### List of Chapters: - -* 01: [JavaScript: a quick overview](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter01) -* 02: [Arrays](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter02) -* 03: [Stacks](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter03) -* 04: [Queues](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter04) -* 05: [Linked Lists](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter05) -* 06: [Sets](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter06) -* 07: [Dictionaries and Hashes](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter07) -* 08: [Trees](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter08) -* 09: [Graphs](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter09) -* 10: [Sorting and searching algorithms](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter10) -* 11: [Pattern of algorithms](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter11) -* 12: [Algorithm Complexity](https://github.com/loiane/javascript-datastructures-algorithms/tree/second-edition/chapter12) - -### First Edition source code: - -Please refer to [this link](https://github.com/loiane/javascript-datastructures-algorithms/tree/master) + Book link - third edition: + - [Packt](https://www.packtpub.com/web-development/learning-javascript-data-structures-and-algorithms-third-edition) + - [Amazon](http://a.co/cbMlYmJ) + - [Chinese version](http://www.ituring.com.cn/book/2653) + - [Brazilian Portuguese version](https://novatec.com.br/livros/estruturas-de-dados-algoritmos-em-javascript-2ed/) ### Found an issue or have a question? diff --git a/chapter01/01-HelloWorld.js b/chapter01/01-HelloWorld.js deleted file mode 100755 index 89833849..00000000 --- a/chapter01/01-HelloWorld.js +++ /dev/null @@ -1,8 +0,0 @@ -function output(t) { - document.write('

' + t + '

'); - return; -} - -alert('Hello, World!'); -console.log('Hello, World!'); -output('Hello, World!'); \ No newline at end of file diff --git a/chapter01/02-Variables.js b/chapter01/02-Variables.js deleted file mode 100644 index 2920e5be..00000000 --- a/chapter01/02-Variables.js +++ /dev/null @@ -1,37 +0,0 @@ -var num = 1; //{1} -num = 3; //{2} - -var price = 1.5; //{3} -var name = 'Packt'; //{4} -var trueValue = true; //{5} -var nullVar = null; //{6} -var und; //7 - -console.log("num: "+ num); -console.log("name: "+ name); -console.log("trueValue: "+ trueValue); -console.log("price: "+ price); -console.log("nullVar: "+ nullVar); -console.log("und: "+ und); - -//******* Variable Scope - -var myVariable = 'global'; -myOtherVariable = 'global'; - -function myFunction(){ - var myVariable = 'local'; - return myVariable; -} - -function myOtherFunction(){ - myOtherVariable = 'local'; - return myOtherVariable; -} - -console.log(myVariable); //{1} -console.log(myFunction()); //{2} - -console.log(myOtherVariable); //{3} -console.log(myOtherFunction()); //{4} -console.log(myOtherVariable); //{5} \ No newline at end of file diff --git a/chapter01/04-TruthyFalsy.js b/chapter01/04-TruthyFalsy.js deleted file mode 100755 index d700cd2c..00000000 --- a/chapter01/04-TruthyFalsy.js +++ /dev/null @@ -1,23 +0,0 @@ -function testTruthy(val){ - return val ? console.log('truthy') : console.log('falsy'); -} - -testTruthy(true); //true -testTruthy(false); //false -testTruthy(new Boolean(false)); //true (object is always true) - -testTruthy(''); //false -testTruthy('Packt'); //true -testTruthy(new String('')); //true (object is always true) - -testTruthy(1); //true -testTruthy(-1); //true -testTruthy(NaN); //false -testTruthy(new Number(NaN)); //true (object is always true) - -testTruthy({}); //true (object is always true) - -var obj = {name:'John'}; -testTruthy(obj); //true -testTruthy(obj.name); //true -testTruthy(obj.age); //age (prop does not exist) \ No newline at end of file diff --git a/chapter01/05-EqualsOperators.js b/chapter01/05-EqualsOperators.js deleted file mode 100755 index 253c21b9..00000000 --- a/chapter01/05-EqualsOperators.js +++ /dev/null @@ -1,36 +0,0 @@ -//Packt == true - -console.log('packt' ? true : false); -//outputs true - -console.log('packt' == true); -//1 - converts Boolean using toNumber -//'packt' == 1 -//2 - converts String using toNumber -//NaN == 1 -//outputs false - -console.log('packt' == false); -//1 - converts Boolean using toNumber -//'packt' == 0 -//2 - converts String using toNumber -//NaN == 0 -//outputs false - -console.log([0] == true); -//1 - converts Boolean using toNumber -//[0] == 1 -//2 - converts Object using toPrimitive -//2.1 - [0].valueOf() is not primitive -//2.2 - [0].toString is 0 -//0 == 1 -//outputs false - -//******************************* === -console.log('packt' === true); //false - -console.log('packt' === 'packt'); //true - -var person1 = {name:'John'}; -var person2 = {name:'John'}; -console.log(person1 === person2); //false, different objects \ No newline at end of file diff --git a/chapter01/06-ConditionalStatements.js b/chapter01/06-ConditionalStatements.js deleted file mode 100755 index c7256c80..00000000 --- a/chapter01/06-ConditionalStatements.js +++ /dev/null @@ -1,51 +0,0 @@ -/* Example 01 - if */ -var num = 1; -if (num === 1) { - console.log("num is equal to 1"); -} - -/* Example 02 - if-else */ -var num = 0; -if (num === 1) { - console.log("num is equal to 1"); -} else { - console.log("num is not equal to 1, the value of num is " + num); -} - -/* Example 03 - if-else-if-else... */ -var month = 5; -if (month === 1) { - console.log("January"); -} else if (month === 2){ - console.log("February"); -} else if (month === 3){ - console.log("March"); -} else { - console.log("Month is not January, February or March"); -} - -/* Example 04 - switch */ -var month = 5; -switch(month) { - case 1: - console.log("January"); - break; - case 2: - console.log("February"); - break; - case 3: - console.log("March"); - break; - default: - console.log("Month is not January, February or March"); -} - -/* Example 05 - ternary operator - if..else */ -if (num === 1){ - num--; -} else { - num++; -} - -//is the same as -(num === 1) ? num-- : num++; \ No newline at end of file diff --git a/chapter01/10-ObjectOrientedJS.js b/chapter01/10-ObjectOrientedJS.js deleted file mode 100644 index c67a6c78..00000000 --- a/chapter01/10-ObjectOrientedJS.js +++ /dev/null @@ -1,42 +0,0 @@ -/* Object example 1 */ - -var obj = new Object(); - -/* Object example 2 */ - -var obj = {}; - -obj = { - name: { - first: 'Gandalf', - last: 'the Grey' - }, - address: 'Middle Earth' -}; - -/* Object example 3 */ - -function Book(title, pages, isbn){ - this.title = title; - this.pages = pages; - this.isbn = isbn; - this.printIsbn = function(){ - console.log(this.isbn); - } -} - -var book = new Book('title', 'pag', 'isbn'); - -console.log(book.title); //outputs the book title - -book.title = 'new title'; //update the value of the book title - -console.log(book.title); //outputs the updated value - -Book.prototype.printTitle = function(){ - console.log(this.title); -}; - -book.printTitle(); - -book.printIsbn(); \ No newline at end of file diff --git a/chapter01/11-ES6letconst.js b/chapter01/11-ES6letconst.js deleted file mode 100644 index 6be49b70..00000000 --- a/chapter01/11-ES6letconst.js +++ /dev/null @@ -1,47 +0,0 @@ -//******* EcmaScript 6: let and const keywords -// EcmaScript 6 Constants -const PI = 3.141593; -//PI = 3.0; //throws error -console.log(PI); - -//******* EcmaScript 6: let is the new var -var framework = 'Angular'; -var framework = 'React'; -console.log(framework); - -let language = 'JavaScript!'; -//let language = 'Ruby!'; //throws error -console.log(language); - -//******* EcmaScript 6: variables scope -let movie = 'Lord of the Rings'; -//var movie = 'Batman v Superman'; //throws error, variable movie already declared - -function starWarsFan(){ - let movie = 'Star Wars'; - return movie; -} - -function marvelFan(){ - movie = 'The Avengers'; - return movie; -} - -function blizzardFan(){ - let isFan = true; - let phrase = 'Warcraft'; - console.log('Before if: ' + phrase); - if (isFan){ - let phrase = 'initial text'; - phrase = 'For the Horde!'; - console.log('Inside if: ' + phrase); - } - phrase = 'For the Alliance!'; - console.log('After if: ' + phrase); -} - -console.log(movie); -console.log(starWarsFan()); -console.log(marvelFan()); -console.log(movie); -blizzardFan(); \ No newline at end of file diff --git a/chapter01/12-Es6StringTemplates.js b/chapter01/12-Es6StringTemplates.js deleted file mode 100644 index 30dc62c1..00000000 --- a/chapter01/12-Es6StringTemplates.js +++ /dev/null @@ -1,7 +0,0 @@ -// Template literals -var book = { - name: 'Learning JavaScript DataStructures and Algorithms' -}; - -console.log(`You are reading ${book.name}., - and this is a new line`); \ No newline at end of file diff --git a/chapter01/13-ES6ArrowFunctions.js b/chapter01/13-ES6ArrowFunctions.js deleted file mode 100644 index 317d576f..00000000 --- a/chapter01/13-ES6ArrowFunctions.js +++ /dev/null @@ -1,10 +0,0 @@ -//ES6: arrow functions -let circleArea = (r) => { - const PI = 3.14; - let area = PI * r * r; - return area; -} -console.log(circleArea(2)); - -let circleArea2 = (r) => 3.14 * r * r; -console.log(circleArea2(2)); \ No newline at end of file diff --git a/chapter01/14-ES6ParameterHandling.js b/chapter01/14-ES6ParameterHandling.js deleted file mode 100644 index af23585c..00000000 --- a/chapter01/14-ES6ParameterHandling.js +++ /dev/null @@ -1,37 +0,0 @@ -//******* EcmaScript 6: Default Parameter Values -function sum (x = 1, y = 2, z = 3) { - return x + y + z -}; -console.log(sum(4,2)); //outpus 9 - -//function above is the same as -function sum2 (x, y, z) { - if (x === undefined) - x = 1; - if (y === undefined) - y = 2; - if (z === undefined) - z = 3; - return x + y + z; -}; -console.log(sum2(4,2)); //outpus 9 - -//******* EcmaScript 6: spread operator ('...') -var params = [3, 4, 5]; -console.log(sum(...params)); - -var numbers = [1, 2, ...params]; //pushing values into array -console.log(numbers); - -//******* EcmaScript 6: rest parameter ('...') -function restParamaterFunction (x, y, ...a) { - return (x + y) * a.length; -} -console.log(restParamaterFunction(1, 2, "hello", true, 7)); // outputs 9; - -//code above is the same as ES5: -function restParamaterFunction2 (x, y) { - var a = Array.prototype.slice.call(arguments, 2); - return (x + y) * a.length; -}; -console.log(restParamaterFunction2(1, 2, "hello", true, 7)); diff --git a/chapter01/15-ES6EnhancedObjectProperties.js b/chapter01/15-ES6EnhancedObjectProperties.js deleted file mode 100644 index 5f1dd9f1..00000000 --- a/chapter01/15-ES6EnhancedObjectProperties.js +++ /dev/null @@ -1,34 +0,0 @@ -// Destructuring Assignment + Property Shorthand -var [x, y] = ['a', 'b']; -var obj = { x, y }; -console.log(obj); // { x: "a", y: "b" } - -[x, y] = [y, x]; -var temp = x; -x = y; -y = temp; - -//code above is the same as -var x = 'a'; -var y = 'b'; -var obj2 = { x: x, y: y }; -console.log(obj2); // { x: "a", y: "b" } - - -// Method Properties -var hello = { - name : 'abcdef', - printHello(){ - console.log('Hello'); - } -} -console.log(hello.printHello()); - -//code above is the same as: -var hello2 = { - name: 'abcdef', - printHello: function printHello() { - console.log('Hello'); - } -}; -console.log(hello2.printHello()); \ No newline at end of file diff --git a/chapter01/16-ES6Classes.js b/chapter01/16-ES6Classes.js deleted file mode 100644 index 2ec073d9..00000000 --- a/chapter01/16-ES6Classes.js +++ /dev/null @@ -1,88 +0,0 @@ -// ES6 classes -class Book { - constructor (title, pages, isbn) { - this.title = title; - this.pages = pages; - this.isbn = isbn; - } - printIsbn(){ - console.log(this.isbn); - } -} - -let book = new Book('title', 'pag', 'isbn'); - -console.log(book.title); //outputs the book title - -book.title = 'new title'; //update the value of the book title - -console.log(book.title); //outputs the book title - - -//inheritance -class ITBook extends Book { - - constructor (title, pages, isbn, technology) { - super(title, pages, isbn); - this.technology = technology; - } - - printTechnology(){ - console.log(this.technology); - } -} - -let jsBook = new ITBook('Learning JS Algorithms', '200', '1234567890', 'JavaScript'); - -console.log(jsBook.title); -console.log(jsBook.printTechnology()); - -//getter and setters -class Person { - - constructor (name) { - this._name = name; - } - - get name() { - return this._name; - } - - set name(value) { - this._name = value; - } -} - -let lotrChar = new Person('Frodo'); -console.log(lotrChar.name); -lotrChar.name = 'Gandalf'; -console.log(lotrChar.name); - -lotrChar._name = 'Sam'; -console.log(lotrChar.name); - - -//using symbols for private atributes - -var _name = Symbol(); -class Person2 { - - constructor (name) { - this[_name] = name; - } - - get name() { - return this[_name]; - } - - set name(value) { - this[_name] = value; - } -} - -let lotrChar2 = new Person2('Frodo'); -console.log(lotrChar2.name); -lotrChar2.name = 'Gandalf'; -console.log(lotrChar2.name); - -console.log(Object.getOwnPropertySymbols(lotrChar2)); \ No newline at end of file diff --git a/chapter02/01-Introduction.js b/chapter02/01-Introduction.js deleted file mode 100755 index 93d80a8d..00000000 --- a/chapter02/01-Introduction.js +++ /dev/null @@ -1,12 +0,0 @@ -var averageTempJan = 31.9; -var averageTempFeb = 35.3; -var averageTempMar = 42.4; -var averageTempApr = 52; -var averageTempMay = 60.8; - -var averageTemp = []; -averageTemp[0] = 31.9; -averageTemp[1] = 35.3; -averageTemp[2] = 42.4; -averageTemp[3] = 52; -averageTemp[4] = 60.8; diff --git a/chapter02/02-CreatingAndInitialingArrays.js b/chapter02/02-CreatingAndInitialingArrays.js deleted file mode 100755 index 1b20431e..00000000 --- a/chapter02/02-CreatingAndInitialingArrays.js +++ /dev/null @@ -1,34 +0,0 @@ -var daysOfWeek = []; - -var daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; - -var daysOfWeek = new Array(); //{1} - -var daysOfWeek = new Array(7); //{2} - -console.log(daysOfWeek.length); - -var daysOfWeek = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); //{3} - -for (var i=0; i=0; i--){ - numbers[i] = numbers[i-1]; -} - -numbers[0] = -1; - -//printArray(numbers); - -//using method unshift -numbers.unshift(-2); - -//printArray(numbers); - -numbers.unshift(-4, -3); - -//printArray(numbers); - -//**** Removing elements - -numbers.pop(); - -//remove first position manually -/*for (var i=0; i b) { - return 1; - } - // a must be equal to b - return 0; -} - -console.log(numbers.sort(compare)); - -//Sorting objects - -var friends = [ - {name: 'John', age: 30}, - {name: 'Ana', age: 20}, - {name: 'Chris', age: 25} -]; - -function comparePerson(a, b){ - if (a.age < b.age){ - return -1 - } - if (a.age > b.age){ - return 1 - } - return 0; -} - -console.log(friends.sort(comparePerson)); - -var names =['Ana', 'ana', 'john', 'John']; -console.log(names.sort()); - -console.log(names.sort(function(a, b){ - if (a.toLowerCase() < b.toLowerCase()){ - return -1 - } - if (a.toLowerCase() > b.toLowerCase()){ - return 1 - } - return 0; -})); - -var names2 = ['Maève', 'Maeve']; -console.log(names2.sort(function(a, b){ - return a.localeCompare(b); -})); - -//*** toString -console.log(numbers.toString()); - -console.log(numbers.indexOf(10)); -console.log(numbers.indexOf(100)); - -numbers.push(10); -console.log(numbers.lastIndexOf(10)); -console.log(numbers.lastIndexOf(100)); - -var numbersString = numbers.join('-'); -console.log(numbersString); \ No newline at end of file diff --git a/chapter02/06-ES6Methods.html b/chapter02/06-ES6Methods.html deleted file mode 100644 index fdbeda65..00000000 --- a/chapter02/06-ES6Methods.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter02/06-ES6Methods.js b/chapter02/06-ES6Methods.js deleted file mode 100644 index bf4eb36a..00000000 --- a/chapter02/06-ES6Methods.js +++ /dev/null @@ -1,112 +0,0 @@ -let numbers = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]; - -//********** forEch using arrow functions -console.log('forEach using arrow functions'); - -numbers.forEach(x => { - console.log((x % 2 == 0)); -}); - -//********** using for..of loop -console.log('using for..of loop'); - -for (let n of numbers) { - console.log((n % 2 == 0) ? 'even' : 'odd'); -} - -//********** Using the new ES6 iterator (@@iterator) -console.log('Using the new ES6 iterator (@@iterator)'); - -let iterator = numbers[Symbol.iterator](); -console.log(iterator.next().value); //1 -console.log(iterator.next().value); //2 -console.log(iterator.next().value); //3 -console.log(iterator.next().value); //4 -console.log(iterator.next().value); //5 - -//********** Array entries, keys and values -console.log('Array entries, keys and values'); - -console.log('Array.entries'); -let aEntries = numbers.entries(); //retrieve iterator of key/value -console.log(aEntries.next().value); // [0, 1] - position 0, value 1 -console.log(aEntries.next().value); // [1, 2] - position 1, value 2 -console.log(aEntries.next().value); // [2, 3] - position 2, value 3 - -console.log('Array.keys'); -let aKeys = numbers.keys(); //retrieve iterator of keys -console.log(aKeys.next()); // {value: 0, done: false } done false means iterator has more values -console.log(aKeys.next()); // {value: 1, done: false } -console.log(aKeys.next()); // {value: 2, done: false } - -console.log('Array.values'); -let aValues = numbers.values(); -console.log(aValues.next()); // {value: 1, done: false } done false means iterator has more values -console.log(aValues.next()); // {value: 2, done: false } -console.log(aValues.next()); // {value: 3, done: false } - -//********** Using the from method -console.log('Using the from method'); - -let evens = Array.from(numbers, x => (x % 2 == 0)); -console.log(evens); - -let numbers2 = Array.from(numbers); -console.log(numbers2); - -//********** Using Array.of -console.log('Using Array.of'); - -let numbers3 = Array.of(1); -let numbers4 = Array.of(1,2,3,4,5,6); -let numbersCopy = Array.of(...numbers4); -console.log(numbers3); -console.log(numbers4); -console.log(numbersCopy); - -//********** Using the fill method -console.log('Using the fill method'); - -numbersCopy.fill(0); -console.log(numbersCopy); - -numbersCopy.fill(2, 1); -console.log(numbersCopy); - -numbersCopy.fill(1, 3, 5); -console.log(numbersCopy); - -let ones = Array(6).fill(1); -console.log(ones); - -//********** Using the copyWithin method -console.log('Using the copyWithin method'); - -let copyArray = [1, 2, 3, 4, 5, 6]; -console.log(copyArray); - -copyArray = copyArray.copyWithin(0, 3); //pos 3 value is copied to pos 0 -console.log(copyArray); - -copyArray = [1, 2, 3, 4, 5, 6]; -copyArray = copyArray.copyWithin(1, 3, 5); //pos 3-4 values are copied to pos 1-2 -console.log(copyArray); - -//********** methods find and findIndex -console.log('methods find and findIndex'); - -function multipleOf13(element, index, array) { - return (element % 13 == 0) ? true : false; -} - -console.log(numbers.find(multipleOf13)); -console.log(numbers.findIndex(multipleOf13)); - -//********** EcmaScript 7: using the method includes -console.log('EcmaScript 7: using the method includes'); - -console.log(numbers.includes(15)); -console.log(numbers.includes(20)); - -let numbers5 = [7,6,5,4,3,2,1]; -console.log(numbers5.includes(4,5)); diff --git a/chapter02/07-TypedArrays.js b/chapter02/07-TypedArrays.js deleted file mode 100644 index 66a5b29a..00000000 --- a/chapter02/07-TypedArrays.js +++ /dev/null @@ -1,26 +0,0 @@ -let length = 5; -let int16 = new Int16Array(length); - -let array16 = []; -array16.length = length; - -for (let i=0; i - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter03/02-UsingStacks.js b/chapter03/02-UsingStacks.js deleted file mode 100644 index 9876e892..00000000 --- a/chapter03/02-UsingStacks.js +++ /dev/null @@ -1,24 +0,0 @@ -let stack = new Stack3(); - console.log(stack.isEmpty()); //outputs true - stack.push(5); - stack.push(8); - console.log(stack.peek()); // outputs 8 - stack.push(11); - console.log(stack.size()); // outputs 3 - console.log(stack.isEmpty()); //outputs false - stack.push(15); - stack.pop(); - stack.pop(); - console.log(stack.size()); // outputs 2 - stack.print(); // outputs [5, 8] - - -//how to ensure true privacy -//in case using Stack 2 uncomment code below -/*let objectSymbols = Object.getOwnPropertySymbols(stack); - - console.log(objectSymbols.length); // 1 - console.log(objectSymbols); // [Symbol()] - console.log(objectSymbols[0]); // Symbol() - stack[objectSymbols[0]].push(1); - stack.print(); //5, 8, 1*/ \ No newline at end of file diff --git a/chapter03/03-BalancedSymbols.html b/chapter03/03-BalancedSymbols.html deleted file mode 100755 index d347fe2e..00000000 --- a/chapter03/03-BalancedSymbols.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter03/03-BalancedSymbols.js b/chapter03/03-BalancedSymbols.js deleted file mode 100644 index 0d4df4c6..00000000 --- a/chapter03/03-BalancedSymbols.js +++ /dev/null @@ -1,41 +0,0 @@ -function parenthesesChecker(symbols){ - - let stack = new Stack(), - balanced = true, - index = 0, - symbol, top, - opens = "([{", - closers = ")]}"; - - while (index < symbols.length && balanced){ - symbol = symbols.charAt(index); - if (opens.indexOf(symbol) >= 0){ - stack.push(symbol); - console.log(`open symbol - stacking ${symbol}`); - } else { - console.log(`close symbol ${symbol}`); - if (stack.isEmpty()){ - balanced = false; - console.log('Stack is empty, no more symbols to pop and compare'); - } else { - top = stack.pop(); - //if (!matches(top, symbol)){ - if (!(opens.indexOf(top) === closers.indexOf(symbol))) { - balanced = false; - console.log(`poping symbol ${top} - is not a match compared to ${symbol}`); - } else { - console.log(`poping symbol ${top} - is is a match compared to ${symbol}`); - } - } - } - index++; - } - if (balanced && stack.isEmpty()){ - return true; - } - return false; -} - -console.log(parenthesesChecker('{([])}')); //true -console.log(parenthesesChecker('{{([][])}()}')); //true -console.log(parenthesesChecker('[{()]')); //false \ No newline at end of file diff --git a/chapter03/04-DecimalToBinary.html b/chapter03/04-DecimalToBinary.html deleted file mode 100755 index a178b773..00000000 --- a/chapter03/04-DecimalToBinary.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter03/04-DecimalToBinary.js b/chapter03/04-DecimalToBinary.js deleted file mode 100755 index d4695b51..00000000 --- a/chapter03/04-DecimalToBinary.js +++ /dev/null @@ -1,52 +0,0 @@ -//233 == 11101001 -//2x(10x10) + 3x(10) + 3x(1) - -function divideBy2(decNumber){ - - var remStack = new Stack(), - rem, - binaryString = ''; - - while (decNumber > 0){ - rem = Math.floor(decNumber % 2); - remStack.push(rem); - decNumber = Math.floor(decNumber / 2); - } - - while (!remStack.isEmpty()){ - binaryString += remStack.pop().toString(); - } - - return binaryString; -} - -console.log(divideBy2(233)); -console.log(divideBy2(10)); -console.log(divideBy2(1000)); - -/* - The folow algorithm converts from base 10 to any base - */ -function baseConverter(decNumber, base){ - - var remStack = new Stack(), - rem, - baseString = '', - digits = '0123456789ABCDEF'; - - while (decNumber > 0){ - rem = Math.floor(decNumber % base); - remStack.push(rem); - decNumber = Math.floor(decNumber / base); - } - - while (!remStack.isEmpty()){ - baseString += digits[remStack.pop()]; - } - - return baseString; -} - -console.log(baseConverter(100345, 2)); -console.log(baseConverter(100345, 8)); -console.log(baseConverter(100345, 16)); \ No newline at end of file diff --git a/chapter03/05-TowerOfHanoi.html b/chapter03/05-TowerOfHanoi.html deleted file mode 100755 index 8e11f147..00000000 --- a/chapter03/05-TowerOfHanoi.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter03/05-TowerOfHanoi.js b/chapter03/05-TowerOfHanoi.js deleted file mode 100644 index ce0fd6dd..00000000 --- a/chapter03/05-TowerOfHanoi.js +++ /dev/null @@ -1,26 +0,0 @@ -function towerOfHanoi(n, from, to, helper){ - - if (n > 0){ - towerOfHanoi(n-1, from, helper, to); - to.push(from.pop()); - console.log('-----'); - console.log('Source: ' + from.toString()); - console.log('Dest: ' + to.toString()); - console.log('Helper: ' + helper.toString()); - towerOfHanoi(n-1, helper, to, from); - } -} - -var source = new Stack(); -source.push(3); -source.push(2); -source.push(1); - -var dest = new Stack(); -var helper = new Stack(); - -towerOfHanoi(source.size(), source, dest, helper); - -source.print(); -helper.print(); -dest.print(); \ No newline at end of file diff --git a/chapter04/01-Queue.js b/chapter04/01-Queue.js deleted file mode 100644 index bb22df69..00000000 --- a/chapter04/01-Queue.js +++ /dev/null @@ -1,32 +0,0 @@ -function Queue() { - - let items = []; - - this.enqueue = function(element){ - items.push(element); - }; - - this.dequeue = function(){ - return items.shift(); - }; - - this.front = function(){ - return items[0]; - }; - - this.isEmpty = function(){ - return items.length == 0; - }; - - this.clear = function(){ - items = []; - }; - - this.size = function(){ - return items.length; - }; - - this.print = function(){ - console.log(items.toString()); - }; -} diff --git a/chapter04/01-Queue2.js b/chapter04/01-Queue2.js deleted file mode 100644 index d4bc9891..00000000 --- a/chapter04/01-Queue2.js +++ /dev/null @@ -1,49 +0,0 @@ -let Queue2 = (function () { - - const items = new WeakMap(); - - class Queue2 { - - constructor () { - items.set(this, []); - } - - enqueue(element) { - let q = items.get(this); - q.push(element); - } - - dequeue() { - let q = items.get(this); - let r = q.shift(); - return r; - } - - front() { - let q = items.get(this); - return q[0]; - } - - isEmpty(){ - return items.get(this).length == 0; - } - - size(){ - let q = items.get(this); - return q.length; - } - - clear(){ - items.set(this, []); - } - - print(){ - console.log(this.toString()); - } - - toString(){ - return items.get(this).toString(); - } - } - return Queue2; -})(); diff --git a/chapter04/02-UsingQueues.html b/chapter04/02-UsingQueues.html deleted file mode 100644 index 611d3571..00000000 --- a/chapter04/02-UsingQueues.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter04/02-UsingQueues.js b/chapter04/02-UsingQueues.js deleted file mode 100644 index 5411bad6..00000000 --- a/chapter04/02-UsingQueues.js +++ /dev/null @@ -1,12 +0,0 @@ -let queue = new Queue2(); -console.log(queue.isEmpty()); //outputs true -queue.enqueue("John"); -queue.enqueue("Jack"); -queue.print(); -queue.enqueue("Camila"); -queue.print(); -console.log(queue.size()); //outputs 3 -console.log(queue.isEmpty()); //outputs false -queue.dequeue(); -queue.dequeue(); -queue.print(); \ No newline at end of file diff --git a/chapter04/03-PriorityQueue.html b/chapter04/03-PriorityQueue.html deleted file mode 100755 index 924bf7c4..00000000 --- a/chapter04/03-PriorityQueue.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter04/03-PriorityQueue.js b/chapter04/03-PriorityQueue.js deleted file mode 100644 index 3b029e4d..00000000 --- a/chapter04/03-PriorityQueue.js +++ /dev/null @@ -1,54 +0,0 @@ -function PriorityQueue() { - - let items = []; - - function QueueElement (element, priority){ // {1} - this.element = element; - this.priority = priority; - } - - this.enqueue = function(element, priority){ - let queueElement = new QueueElement(element, priority); - - let added = false; - for (let i=0; i - - - - - - - - - - \ No newline at end of file diff --git a/chapter04/03-PriorityQueue2.js b/chapter04/03-PriorityQueue2.js deleted file mode 100644 index d629334b..00000000 --- a/chapter04/03-PriorityQueue2.js +++ /dev/null @@ -1,80 +0,0 @@ -let PriorityQueue2 = (function () { - - class QueueElement { - constructor(element, priority){ - this.element = element; - this.priority = priority; - } - } - - const items = new WeakMap(); - - class PriorityQueue2 { //extends Queue2 { //with this approach the private properties are not reachable through inheritance - - constructor () { - items.set(this, []); - } - - enqueue(element, priority){ - let queueElement = new QueueElement(element, priority); - - let q = items.get(this); - - let added = false; - for (let i=0; i - - - - - - - - - - \ No newline at end of file diff --git a/chapter04/04-HotPotato.js b/chapter04/04-HotPotato.js deleted file mode 100644 index d0ce0d98..00000000 --- a/chapter04/04-HotPotato.js +++ /dev/null @@ -1,23 +0,0 @@ -function hotPotato (nameList, num){ - - let queue = new Queue(); - - for (let i=0; i 1){ - for (let i=0; i= 0 && position <= length){ - - let node = new Node(element), - current = head, - previous, - index = 0; - - if (position === 0){ //add on first position - - node.next = current; - head = node; - - } else { - while (index++ < position){ - previous = current; - current = current.next; - } - node.next = current; - previous.next = node; - } - - length++; //update size of list - - return true; - - } else { - return false; - } - }; - - this.removeAt = function(position){ - - //check for out-of-bounds values - if (position > -1 && position < length){ - - let current = head, - previous, - index = 0; - - //removing first item - if (position === 0){ - head = current.next; - } else { - - while (index++ < position){ - - previous = current; - current = current.next; - } - - //link previous with current's next - skip it to remove - previous.next = current.next; - } - - length--; - - return current.element; - - } else { - return null; - } - }; - - this.remove = function(element){ - - let index = this.indexOf(element); - return this.removeAt(index); - }; - - this.indexOf = function(element){ - - let current = head, - index = 0; - - while (current) { - if (element === current.element) { - return index; - } - index++; - current = current.next; - } - - return -1; - }; - - this.isEmpty = function() { - return length === 0; - }; - - this.size = function() { - return length; - }; - - this.getHead = function(){ - return head; - }; - - this.toString = function(){ - - let current = head, - string = ''; - - while (current) { - string += current.element + (current.next ? ', ' : ''); - current = current.next; - } - return string; - - }; - - this.print = function(){ - console.log(this.toString()); - }; -} diff --git a/chapter05/01-LinkedList2.js b/chapter05/01-LinkedList2.js deleted file mode 100644 index 98452857..00000000 --- a/chapter05/01-LinkedList2.js +++ /dev/null @@ -1,170 +0,0 @@ -let LinkedList2 = (function () { - - class Node { - constructor(element){ - this.element = element; - this.next = null; - } - } - - const length = new WeakMap(); - const head = new WeakMap(); - - class LinkedList2 { - - constructor () { - length.set(this, 0); - head.set(this, null); - } - - append(element) { - - let node = new Node(element), - current; - - if (this.getHead() === null) { //first node on list - head.set(this, node); - } else { - - current = this.getHead(); - - //loop the list until find last item - while (current.next) { - current = current.next; - } - - //get last item and assign next to added item to make the link - current.next = node; - } - - //update size of list - let l = this.size(); - l++; - length.set(this, l); - } - - insert(position, element) { - - //check for out-of-bounds values - if (position >= 0 && position <= this.size()) { - - let node = new Node(element), - current = this.getHead(), - previous, - index = 0; - - if (position === 0) { //add on first position - - node.next = current; - head.set(this, node); - - } else { - while (index++ < position) { - previous = current; - current = current.next; - } - node.next = current; - previous.next = node; - } - - //update size of list - let l = this.size(); - l++; - length.set(this, l); - - return true; - - } else { - return false; - } - } - - removeAt(position) { - - //check for out-of-bounds values - if (position > -1 && position < this.size()) { - - let current = this.getHead(), - previous, - index = 0; - - //removing first item - if (position === 0) { - head.set(this, current.next); - } else { - - while (index++ < position) { - - previous = current; - current = current.next; - } - - //link previous with current's next - skip it to remove - previous.next = current.next; - } - - let l = this.size(); - l--; - length.set(this, l); - - return current.element; - - } else { - return null; - } - } - - remove(element) { - - let index = this.indexOf(element); - return this.removeAt(index); - } - - indexOf(element) { - - let current = this.getHead(), - index = 0; - - while (current) { - if (element === current.element) { - return index; - } - index++; - current = current.next; - } - - return -1; - } - - isEmpty() { - return this.size() === 0; - } - - size() { - return length.get(this); - } - - getHead() { - return head.get(this); - } - - toString() { - - let current = this.getHead(), - string = ''; - - while (current) { - string += current.element + (current.next ? ', ' : ''); - current = current.next; - } - return string; - - } - - print() { - console.log(this.toString()); - } - } - - return LinkedList2; -})(); diff --git a/chapter05/02-UsingLinkedLists.html b/chapter05/02-UsingLinkedLists.html deleted file mode 100644 index 97210e70..00000000 --- a/chapter05/02-UsingLinkedLists.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter05/02-UsingLinkedLists.js b/chapter05/02-UsingLinkedLists.js deleted file mode 100644 index bef9d86e..00000000 --- a/chapter05/02-UsingLinkedLists.js +++ /dev/null @@ -1,32 +0,0 @@ -let list = new LinkedList2(); -list.append(15); -list.print(); -console.log(list.indexOf(15)); -list.append(10); -list.print(); -console.log(list.indexOf(10)); -list.append(13); -list.print(); -console.log(list.indexOf(13)); -console.log(list.indexOf(10)); -list.append(11); -list.append(12); -list.print(); -console.log(list.removeAt(1)); -list.print() -console.log(list.removeAt(3)); -list.print(); -list.append(14); -list.print(); -list.insert(0,16); -list.print(); -list.insert(1,17); -list.print(); -list.insert(list.size(),18); -list.print(); -list.remove(16); -list.print(); -list.remove(11); -list.print(); -list.remove(18); -list.print(); \ No newline at end of file diff --git a/chapter05/03-DoublyLinkedList.js b/chapter05/03-DoublyLinkedList.js deleted file mode 100644 index 6d4de9c5..00000000 --- a/chapter05/03-DoublyLinkedList.js +++ /dev/null @@ -1,217 +0,0 @@ -function DoublyLinkedList() { - - let Node = function(element){ - - this.element = element; - this.next = null; - this.prev = null; //NEW - }; - - let length = 0; - let head = null; - let tail = null; //NEW - - this.append = function(element){ - - let node = new Node(element), - current; - - if (head === null){ //first node on list - head = node; - tail = node; //NEW - } else { - - //attach to the tail node //NEW - tail.next = node; - node.prev = tail; - tail = node; - } - - length++; //update size of list - }; - - this.insert = function(position, element){ - - //check for out-of-bounds values - if (position >= 0 && position <= length){ - - let node = new Node(element), - current = head, - previous, - index = 0; - - if (position === 0){ //add on first position - - if (!head){ //NEW - head = node; - tail = node; - } else { - node.next = current; - current.prev = node; //NEW {1} - head = node; - } - - } else if (position === length) { //last item //NEW - - current = tail; // {2} - current.next = node; - node.prev = current; - tail = node; - - } else { - while (index++ < position){ //{3} - previous = current; - current = current.next; - } - node.next = current; - previous.next = node; - - current.prev = node; //NEW - node.prev = previous; //NEW - } - - length++; //update size of list - - return true; - - } else { - return false; - } - }; - - this.removeAt = function(position){ - - //check for out-of-bounds values - if (position > -1 && position < length){ - - let current = head, - previous, - index = 0; - - //removing first item - if (position === 0){ - - head = current.next; // {1} - - //if there is only one item, then we update tail as well //NEW - if (length === 1){ // {2} - tail = null; - } else { - head.prev = null; // {3} - } - - } else if (position === length-1){ //last item //NEW - - current = tail; // {4} - tail = current.prev; - tail.next = null; - - } else { - - while (index++ < position){ // {5} - - previous = current; - current = current.next; - } - - //link previous with current's next - skip it to remove - previous.next = current.next; // {6} - current.next.prev = previous; //NEW - } - - length--; - - return current.element; - - } else { - return null; - } - }; - - this.remove = function(element){ - - let index = this.indexOf(element); - return this.removeAt(index); - }; - - this.indexOf = function(element){ - - let current = head, - index = -1; - - //check first item - if (element == current.element){ - return 0; - } - - index++; - - //check in the middle of the list - while(current.next){ - - if (element == current.element){ - return index; - } - - current = current.next; - index++; - } - - //check last item - if (element == current.element){ - return index; - } - - return -1; - }; - - this.isEmpty = function() { - return length === 0; - }; - - this. size = function() { - return length; - }; - - this.toString = function(){ - - let current = head, - s = current ? current.element : ''; - - while(current && current.next){ - current = current.next; - s += ', ' + current.element; - } - - return s; - }; - - this.inverseToString = function() { - - let current = tail, - s = current ? current.element : ''; - - while(current && current.prev){ - current = current.prev; - s += ', ' + current.element; - } - - return s; - }; - - this.print = function(){ - console.log(this.toString()); - }; - - this.printInverse = function(){ - console.log(this.inverseToString()); - }; - - this.getHead = function(){ - return head; - }; - - this.getTail = function(){ - return tail; - } -} \ No newline at end of file diff --git a/chapter05/03-DoublyLinkedList2.js b/chapter05/03-DoublyLinkedList2.js deleted file mode 100644 index 9fe7d87b..00000000 --- a/chapter05/03-DoublyLinkedList2.js +++ /dev/null @@ -1,242 +0,0 @@ -let DoublyLinkedList2 = (function () { - - class Node { - constructor(element) { - this.element = element; - this.next = null; - this.prev = null; //NEW - } - } - - const length = new WeakMap(); - const head = new WeakMap(); - const tail = new WeakMap(); //NEW - - class DoublyLinkedList2 { - - constructor () { - length.set(this, 0); - head.set(this, null); - tail.set(this, null); - } - - append(element) { - - let node = new Node(element), - current, _tail; - - if (this.getHead() === null) { //first node on list - head.set(this, node); - tail.set(this, node); //NEW - } else { - //attach to the tail node //NEW - _tail = this.getTail(); - _tail.next = node; - node.prev = _tail; - tail.set(this, node); - } - - //update size of list - let l = this.size(); - l++; - length.set(this, l); - } - - insert(position, element) { - - //check for out-of-bounds values - if (position >= 0 && position <= this.size()) { - - let node = new Node(element), - current = this.getHead(), - previous, - index = 0; - - if (position === 0) { //add on first position - - if (!this.getHead()) { //NEW - head.set(this, node); - tail.set(this, node); - } else { - node.next = current; - current.prev = node; //NEW {1} - head.set(this, node); - } - - } else if (position === this.size()) { //last item //NEW - - current = tail; // {2} - current.next = node; - node.prev = current; - tail.set(this, node); - - } else { - while (index++ < position) { //{3} - previous = current; - current = current.next; - } - node.next = current; - previous.next = node; - - current.prev = node; //NEW - node.prev = previous; //NEW - } - - //update size of list - let l = this.size(); - l++; - length.set(this, l); - - return true; - - } else { - return false; - } - } - - removeAt(position) { - - //check for out-of-bounds values - if (position > -1 && position < this.size()) { - - let _head = this.getHead(), - _tail = this.getTail(), - current = _head, - previous, - index = 0; - - //removing first item - if (position === 0) { - - _head = current.next; // {1} - - //if there is only one item, then we update tail as well //NEW - if (this.size() === 1) { // {2} - _tail = null; - } else { - _head.prev = null; // {3} - } - - } else if (position === this.size() - 1) { //last item //NEW - - current = _tail; // {4} - _tail = current.prev; - _tail.next = null; - - } else { - - while (index++ < position) { // {5} - - previous = current; - current = current.next; - } - - //link previous with current's next - skip it to remove - previous.next = current.next; // {6} - current.next.prev = previous; //NEW - } - - head.set(this,_head); - tail.set(this,_tail); - - //update size of list - let l = this.size(); - l--; - length.set(this, l); - - return current.element; - - } else { - return null; - } - } - - remove(element) { - - let index = this.indexOf(element); - return this.removeAt(index); - } - - indexOf(element) { - - let current = this.getHead(), - index = -1; - - //check first item - if (element == current.element) { - return 0; - } - - index++; - - //check in the middle of the list - while (current.next) { - - if (element == current.element) { - return index; - } - - current = current.next; - index++; - } - - //check last item - if (element == current.element) { - return index; - } - - return -1; - } - - isEmpty() { - return this.size() === 0; - } - - size() { - return length.get(this); - } - - toString() { - - let current = this.getHead(), - s = current ? current.element : ''; - - while (current && current.next) { - current = current.next; - s += ', ' + current.element; - } - - return s; - } - - inverseToString() { - - let current = this.getTail(), - s = current ? current.element : ''; - - while (current && current.prev) { - current = current.prev; - s += ', ' + current.element; - } - - return s; - } - - print() { - console.log(this.toString()); - } - - printInverse() { - console.log(this.inverseToString()); - } - - getHead() { - return head.get(this); - } - - getTail() { - return tail.get(this); - } - } - return DoublyLinkedList2; -})(); \ No newline at end of file diff --git a/chapter05/04-UsingDoublyLinkedLists.html b/chapter05/04-UsingDoublyLinkedLists.html deleted file mode 100644 index 58f959d5..00000000 --- a/chapter05/04-UsingDoublyLinkedLists.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter05/04-UsingDoublyLinkedLists.js b/chapter05/04-UsingDoublyLinkedLists.js deleted file mode 100644 index 9ad4a17c..00000000 --- a/chapter05/04-UsingDoublyLinkedLists.js +++ /dev/null @@ -1,49 +0,0 @@ -let list = new DoublyLinkedList2(); - -list.append(15); -list.print(); -list.printInverse(); - -list.append(16); -list.print(); -list.printInverse(); - -list.append(17); -list.print(); -list.printInverse(); - -list.insert(0,13); -list.print(); -list.printInverse(); - -list.insert(4,18); -list.print(); -list.printInverse(); - -list.insert(1,14); -list.print(); -list.printInverse(); - -list.removeAt(0); -list.print(); -list.printInverse(); - -list.removeAt(list.size()-1); -list.print(); -list.printInverse(); - -list.removeAt(1); -list.print(); -list.printInverse(); - -list.remove(16); -list.print(); -list.printInverse(); - -list.remove(14); -list.print(); -list.printInverse(); - -list.remove(17); -list.print(); -list.printInverse(); \ No newline at end of file diff --git a/chapter05/05-CircularLinkedList.js b/chapter05/05-CircularLinkedList.js deleted file mode 100644 index c3151148..00000000 --- a/chapter05/05-CircularLinkedList.js +++ /dev/null @@ -1,190 +0,0 @@ -function CircularLinkedList() { - - let Node = function(element){ - - this.element = element; - this.next = null; - }; - - let length = 0; - let head = null; - - this.append = function(element){ - - let node = new Node(element), - current; - - if (head === null){ //first node on list - head = node; - } else { - - current = head; - - //loop the list until find last item - while(current.next !== head){ //last element will be head instead of NULL - current = current.next; - } - - //get last item and assign next to added item to make the link - current.next = node; - } - - //set node.next to head - to have circular list - node.next = head; - - length++; //update size of list - }; - - this.insert = function(position, element){ - - //check for out-of-bounds values - if (position >= 0 && position <= length){ - - let node = new Node(element), - current = head, - previous, - index = 0; - - if (position === 0){ //add on first position - - if(!head){ // if no node in list - head = node; - node.next = head; - }else{ - node.next = current; - - //update last element - while(current.next !== head){ //last element will be head instead of NULL - current = current.next; - } - - head = node; - current.next = head; - } - - - } else { - while (index++ < position){ - previous = current; - current = current.next; - } - node.next = current; - previous.next = node; - } - - length++; //update size of list - - return true; - - } else { - return false; - } - }; - - this.removeAt = function(position){ - - //check for out-of-bounds values - if (position > -1 && position < length){ - - let current = head, - previous, - index = 0; - - //removing first item - if (position === 0){ - - while(current.next !== head){ //needs to update last element first - current = current.next; - } - - head = head.next; - current.next = head; - - } else { //no need to update last element for circular list - - while (index++ < position){ - - previous = current; - current = current.next; - } - - //link previous with current's next - skip it to remove - previous.next = current.next; - } - - length--; - - return current.element; - - } else { - return null; - } - }; - - this.remove = function(element){ - - let index = this.indexOf(element); - return this.removeAt(index); - }; - - this.indexOf = function(element){ - - let current = head, - index = -1; - - //check first item - if (element == current.element){ - return 0; - } - - index++; - - //check in the middle of the list - while(current.next !== head){ - - if (element == current.element){ - return index; - } - - current = current.next; - index++; - } - - //check last item - if (element == current.element){ - return index; - } - - return -1; - }; - - this.isEmpty = function() { - return length === 0; - }; - - this.size = function() { - return length; - }; - - this.getHead = function(){ - return head; - }; - - this.toString = function(){ - - let current = head, - s = current.element; - - while(current.next !== head){ - current = current.next; - s += ', ' + current.element; - } - - return s.toString(); - }; - - this.print = function(){ - console.log(this.toString()); - }; -} - diff --git a/chapter05/05-CircularLinkedList2.js b/chapter05/05-CircularLinkedList2.js deleted file mode 100644 index 6f7574ef..00000000 --- a/chapter05/05-CircularLinkedList2.js +++ /dev/null @@ -1,204 +0,0 @@ -let CircularLinkedList2 = (function () { - - class Node { - constructor(element) { - this.element = element; - this.next = null; - } - } - - const length = new WeakMap(); - const head = new WeakMap(); - - class CircularLinkedList2 { - - constructor () { - length.set(this, 0); - head.set(this, null); - } - - append(element) { - - let node = new Node(element), - current; - - if (this.getHead() === null) { //first node on list - head.set(this, node); - } else { - - current = this.getHead(); - - //loop the list until find last item - while (current.next !== this.getHead()) { //last element will be head instead of NULL - current = current.next; - } - - //get last item and assign next to added item to make the link - current.next = node; - } - - //set node.next to head - to have circular list - node.next = this.getHead(); - - //update size of list - let l = this.size(); - l++; - length.set(this, l); - } - - insert(position, element) { - - //check for out-of-bounds values - if (position >= 0 && position <= this.size()) { - - let node = new Node(element), - current = this.getHead(), - previous, - index = 0; - - if (position === 0) { //add on first position - - if(!this.getHead()) { // if no node in list - head.set(this, node); - node.next = this.getHead(); - } else { - node.next = current; - //update last element - while(current.next !== this.getHead()) { //last element will be head instead of NULL - current = current.next; - } - head.set(this, node); - current.next = this.getHead(); - } - - } else { - while (index++ < position) { - previous = current; - current = current.next; - } - node.next = current; - previous.next = node; - } - - //update size of list - let l = this.size(); - l++; - length.set(this, l); - - return true; - - } else { - return false; - } - } - - removeAt(position) { - - //check for out-of-bounds values - if (position > -1 && position < this.size()) { - - let current = this.getHead(), - previous, - index = 0; - - //removing first item - if (position === 0) { - - while (current.next !== this.getHead()) { //needs to update last element first - current = current.next; - } - - head.set(this, this.getHead().next); - current.next = this.getHead(); - - } else { //no need to update last element for circular list - - while (index++ < position) { - - previous = current; - current = current.next; - } - - //link previous with current's next - skip it to remove - previous.next = current.next; - } - - let l = this.size(); - l--; - length.set(this, l); - - return current.element; - - } else { - return null; - } - } - - remove(element) { - - let index = this.indexOf(element); - return this.removeAt(index); - } - - indexOf(element) { - - let current = this.getHead(), - index = -1; - - //check first item - if (element == current.element) { - return 0; - } - - index++; - - //check in the middle of the list - while (current.next !== this.getHead()) { - - if (element == current.element) { - return index; - } - - current = current.next; - index++; - } - - //check last item - if (element == current.element) { - return index; - } - - return -1; - } - - isEmpty() { - return this.size() === 0; - } - - size() { - return length.get(this); - } - - getHead() { - return head.get(this); - } - - toString() { - - let current = this.getHead(), - s = current.element; - - while (current.next !== this.getHead()) { - current = current.next; - s += ', ' + current.element; - } - - return s.toString(); - } - - print() { - console.log(this.toString()); - } - } - return CircularLinkedList2; -})(); diff --git a/chapter05/06-UsingCircularLinkedList.html b/chapter05/06-UsingCircularLinkedList.html deleted file mode 100644 index ab39ba27..00000000 --- a/chapter05/06-UsingCircularLinkedList.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter05/06-UsingCircularLinkedList.js b/chapter05/06-UsingCircularLinkedList.js deleted file mode 100644 index a1feebbb..00000000 --- a/chapter05/06-UsingCircularLinkedList.js +++ /dev/null @@ -1,28 +0,0 @@ -let circularLinkedList = new CircularLinkedList2(); - -circularLinkedList.append(15); -circularLinkedList.print(); - -circularLinkedList.append(16); -circularLinkedList.print(); - -circularLinkedList.insert(0,14); -circularLinkedList.print(); - -circularLinkedList.insert(1,14.5); -circularLinkedList.print(); - -circularLinkedList.insert(4,17); -circularLinkedList.print(); - -circularLinkedList.removeAt(0); -circularLinkedList.print(); - -circularLinkedList.removeAt(1); -circularLinkedList.print(); - -circularLinkedList.removeAt(2); -circularLinkedList.print(); - -console.log(circularLinkedList.indexOf(14.5)); -console.log(circularLinkedList.indexOf(16)); \ No newline at end of file diff --git a/chapter06/01-Set.js b/chapter06/01-Set.js deleted file mode 100644 index 3fa90281..00000000 --- a/chapter06/01-Set.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * ECMSCRIPT 6 already have a Set class implementation: - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set - * We will try to copy the same functionalities - * @constructor - */ -function Set() { - - let items = {}; - - this.add = function(value){ - if (!this.has(value)){ - items[value] = value; - return true; - } - return false; - }; - - this.delete = function(value){ - if (this.has(value)){ - delete items[value]; - return true; - } - return false; - }; - - this.has = function(value){ - return items.hasOwnProperty(value); - //return value in items; - }; - - this.clear = function(){ - items = {}; - }; - - /** - * Modern browsers function - * IE9+, FF4+, Chrome5+, Opera12+, Safari5+ - * @returns {Number} - */ - this.size = function(){ - return Object.keys(items).length; - }; - - /** - * cross browser compatibility - legacy browsers - * for modern browsers use size function - * @returns {number} - */ - this.sizeLegacy = function(){ - let count = 0; - for(let key in items) { - if(items.hasOwnProperty(key)) - ++count; - } - return count; - }; - - /** - * Modern browsers function - * IE9+, FF4+, Chrome5+, Opera12+, Safari5+ - * @returns {Array} - */ - this.values = function(){ - let values = []; - for (let i=0, keys=Object.keys(items); i otherSet.size()){ //{1} - return false; - } else { - let values = this.values(); - for (let i=0; i otherSet.size()){ - return false; - } else { - let values = this.values(); - for (let i=0; i - - - - - - - - - - - \ No newline at end of file diff --git a/chapter06/02-UsingSets.js b/chapter06/02-UsingSets.js deleted file mode 100644 index e74269ac..00000000 --- a/chapter06/02-UsingSets.js +++ /dev/null @@ -1,18 +0,0 @@ -let set = new Set(); - -set.add(1); -console.log(set.values()); //outputs [1] -console.log(set.has(1)); //outputs true -console.log(set.size()); //outputs 1 - -set.add(2); -console.log(set.values()); //outputs [1, 2] -console.log(set.has(2)); //true -console.log(set.size()); //2 -console.log(set.sizeLegacy()); //3 - -set.delete(1); -console.log(set.values()); //outputs [2] - -set.delete(2); -console.log(set.values()); //outputs [] \ No newline at end of file diff --git a/chapter06/03-Operations.html b/chapter06/03-Operations.html deleted file mode 100755 index ff01c7ae..00000000 --- a/chapter06/03-Operations.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter06/03-Operations.js b/chapter06/03-Operations.js deleted file mode 100644 index dc7ece35..00000000 --- a/chapter06/03-Operations.js +++ /dev/null @@ -1,65 +0,0 @@ -//--------- Union ---------- - -let setA = new Set(); -setA.add(1); -setA.add(2); -setA.add(3); - -let setB = new Set(); -setB.add(3); -setB.add(4); -setB.add(5); -setB.add(6); - -let unionAB = setA.union(setB); -console.log(unionAB.values()); - - -//--------- Intersection ---------- - -let setA = new Set(); -setA.add(1); -setA.add(2); -setA.add(3); - -let setB = new Set(); -setB.add(2); -setB.add(3); -setB.add(4); - -let intersectionAB = setA.intersection(setB); -console.log(intersectionAB.values()); - -//--------- Difference ---------- - -let setA = new Set(); -setA.add(1); -setA.add(2); -setA.add(3); - -let setB = new Set(); -setB.add(2); -setB.add(3); -setB.add(4); - -let differenceAB = setA.difference(setB); -console.log(differenceAB.values()); - -//--------- Subset ---------- - -let setA = new Set(); -setA.add(1); -setA.add(2); - -let setB = new Set(); -setB.add(1); -setB.add(2); -setB.add(3); - -let setC = new Set(); -setC.add(2); -setC.add(3); -setC.add(4); - -console.log(setA.subset(setB)); -console.log(setA.subset(setC)); diff --git a/chapter06/04-UsingES6Set.js b/chapter06/04-UsingES6Set.js deleted file mode 100644 index a39e4100..00000000 --- a/chapter06/04-UsingES6Set.js +++ /dev/null @@ -1,71 +0,0 @@ -let set = new Set(); - -set.add(1); -console.log(set.values()); //outputs @Iterator -console.log(set.has(1)); //outputs true -console.log(set.size); //outputs 1 - -set.add(2); -console.log(set.values()); //outputs [1, 2] -console.log(set.has(2)); //true -console.log(set.size); //2 - -set.delete(1); -console.log(set.values()); //outputs [2] - -set.delete(2); -console.log(set.values()); //outputs [] - -let setA = new Set(); -setA.add(1); -setA.add(2); -setA.add(3); - -let setB = new Set(); -setB.add(2); -setB.add(3); -setB.add(4); - -//--------- Union ---------- -let unionAb = new Set(); -for (let x of setA) unionAb.add(x); -for (let x of setB) unionAb.add(x); -console.log(unionAb); - -//--------- Intersection ---------- -let intersection = function(setA, setB){ - let intersectionSet = new Set(); - - for (let x of setA){ - if (setB.has(x)){ - intersectionSet.add(x); - } - } - - return intersectionSet; -}; -let intersectionAB = intersection(setA, setB); -console.log(intersectionAB); - -//alternative - works on FF only -//intersectionAb = new Set([x for (x of setA) if (setB.has(x))]); -//console.log(intersectionAB); - -//--------- Difference ---------- -let difference = function(setA, setB){ - let differenceSet = new Set(); - - for (let x of setA){ - if (!setB.has(x)){ - differenceSet.add(x); - } - } - - return differenceSet; -}; -let differenceAB = difference(setA, setB); -console.log(differenceAB); - -//alternative - works on FF only -//differenceAB = new Set([x for (x of setA) if (!setB.has(x))]); -//console.log(differenceAB); diff --git a/chapter07/01-Dictionaries.js b/chapter07/01-Dictionaries.js deleted file mode 100644 index a22ec419..00000000 --- a/chapter07/01-Dictionaries.js +++ /dev/null @@ -1,59 +0,0 @@ -function Dictionary(){ - - var items = {}; - - this.set = function(key, value){ - items[key] = value; //{1} - }; - - this.delete = function(key){ - if (this.has(key)){ - delete items[key]; - return true; - } - return false; - }; - - this.has = function(key){ - return items.hasOwnProperty(key); - //return value in items; - }; - - this.get = function(key) { - return this.has(key) ? items[key] : undefined; - }; - - this.clear = function(){ - items = {}; - }; - - this.size = function(){ - return Object.keys(items).length; - }; - - this.keys = function(){ - return Object.keys(items); - }; - - this.values = function(){ - var values = []; - for (var k in items) { - if (this.has(k)) { - values.push(items[k]); - } - } - return values; - }; - - this.each = function(fn) { - for (var k in items) { - if (this.has(k)) { - fn(k, items[k]); - } - } - }; - - this.getItems = function(){ - return items; - } -} \ No newline at end of file diff --git a/chapter07/02-UsingDictionaries.html b/chapter07/02-UsingDictionaries.html deleted file mode 100755 index f0f8e0eb..00000000 --- a/chapter07/02-UsingDictionaries.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter07/02-UsingDictionaries.js b/chapter07/02-UsingDictionaries.js deleted file mode 100644 index dc0bf258..00000000 --- a/chapter07/02-UsingDictionaries.js +++ /dev/null @@ -1,19 +0,0 @@ -var dictionary = new Dictionary(); - -dictionary.set('Gandalf', 'gandalf@email.com'); -dictionary.set('John', 'johnsnow@email.com'); -dictionary.set('Tyrion', 'tyrion@email.com'); - -console.log(dictionary.has('Gandalf')); //outputs true -console.log(dictionary.size()); //outputs 3 - -console.log(dictionary.keys()); //outputs ["Gandalf", "John", "Tyrion"] -console.log(dictionary.values()); //outputs ["gandalf@email.com", "johnsnow@email.com", "tyrion@email.com"] -console.log(dictionary.get('Tyrion')); //outputs tyrion@email.com - -dictionary.delete('John'); - -console.log(dictionary.keys()); //outputs ["Gandalf", "Tyrion"] -console.log(dictionary.values()); //outputs ["gandalf@email.com", "tyrion@email.com"] - -console.log(dictionary.getItems()); //Object {Gandalf: "gandalf@email.com", Tyrion: "tyrion@email.com"} diff --git a/chapter07/03-HashTable.js b/chapter07/03-HashTable.js deleted file mode 100755 index c72783aa..00000000 --- a/chapter07/03-HashTable.js +++ /dev/null @@ -1,46 +0,0 @@ -function HashTable() { - - var table = []; - - var loseloseHashCode = function (key) { - var hash = 0; - for (var i = 0; i < key.length; i++) { - hash += key.charCodeAt(i); - } - return hash % 37; - }; - - var djb2HashCode = function (key) { - var hash = 5381; - for (var i = 0; i < key.length; i++) { - hash = hash * 33 + key.charCodeAt(i); - } - return hash % 1013; - }; - - var hashCode = function (key) { - return loseloseHashCode(key); - }; - - this.put = function (key, value) { - var position = hashCode(key); - console.log(position + ' - ' + key); - table[position] = value; - }; - - this.get = function (key) { - return table[hashCode(key)]; - }; - - this.remove = function(key){ - table[hashCode(key)] = undefined; - }; - - this.print = function () { - for (var i = 0; i < table.length; ++i) { - if (table[i] !== undefined) { - console.log(i + ": " + table[i]); - } - } - }; -} \ No newline at end of file diff --git a/chapter07/04-UsingHash.html b/chapter07/04-UsingHash.html deleted file mode 100755 index 104be603..00000000 --- a/chapter07/04-UsingHash.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter07/04-UsingHash.js b/chapter07/04-UsingHash.js deleted file mode 100755 index d0735eeb..00000000 --- a/chapter07/04-UsingHash.js +++ /dev/null @@ -1,29 +0,0 @@ -var hash = new HashTable(); - -hash.put('Gandalf', 'gandalf@email.com'); -hash.put('John', 'johnsnow@email.com'); -hash.put('Tyrion', 'tyrion@email.com'); -hash.put('Aaron', 'aaron@email.com'); -hash.put('Donnie', 'donnie@email.com'); -hash.put('Ana', 'ana@email.com'); -hash.put('Jonathan', 'jonathan@email.com'); -hash.put('Jamie', 'jamie@email.com'); -hash.put('Sue', 'sue@email.com'); -hash.put('Mindy', 'mindy@email.com'); -hash.put('Paul', 'paul@email.com'); -hash.put('Nathan', 'nathan@email.com'); - -console.log('**** Printing Hash **** '); - -hash.print(); - -console.log('**** Get **** '); - -console.log(hash.get('Gandalf')); -console.log(hash.get('Loiane')); - -console.log('**** Remove **** '); - -hash.remove('Gandalf'); -console.log(hash.get('Gandalf')); -hash.print(); \ No newline at end of file diff --git a/chapter07/05-HashCollisionSeparateChaining.js b/chapter07/05-HashCollisionSeparateChaining.js deleted file mode 100644 index 5cac0e7d..00000000 --- a/chapter07/05-HashCollisionSeparateChaining.js +++ /dev/null @@ -1,85 +0,0 @@ -function HashTableSeparateChaining(){ - - var table = []; - - var ValuePair = function(key, value){ - this.key = key; - this.value = value; - - this.toString = function() { - return '[' + this.key + ' - ' + this.value + ']'; - } - }; - - var loseloseHashCode = function (key) { - var hash = 0; - for (var i = 0; i < key.length; i++) { - hash += key.charCodeAt(i); - } - return hash % 37; - }; - - var hashCode = function(key){ - return loseloseHashCode(key); - }; - - this.put = function(key, value){ - var position = hashCode(key); - console.log(position + ' - ' + key); - - if (table[position] == undefined) { - table[position] = new LinkedList(); - } - table[position].append(new ValuePair(key, value)); - }; - - this.get = function(key) { - var position = hashCode(key); - - if (table[position] !== undefined && !table[position].isEmpty()){ - - //iterate linked list to find key/value - var current = table[position].getHead(); - - do { - if (current.element.key === key){ - return current.element.value; - } - current = current.next; - } while(current); - } - return undefined; - }; - - this.remove = function(key){ - - var position = hashCode(key); - - if (table[position] !== undefined){ - - //iterate linked list to find key/value - var current = table[position].getHead(); - - do { - if (current.element.key === key){ - table[position].remove(current.element); - if (table[position].isEmpty()){ - table[position] = undefined; - } - return true; - } - current = current.next; - } while(current); - } - - return false; - }; - - this.print = function() { - for (var i = 0; i < table.length; ++i) { - if (table[i] !== undefined) { - console.log(table[i].toString()); - } - } - }; -} \ No newline at end of file diff --git a/chapter07/06-UsingHashCollisionSeparateChaining.html b/chapter07/06-UsingHashCollisionSeparateChaining.html deleted file mode 100644 index d671e133..00000000 --- a/chapter07/06-UsingHashCollisionSeparateChaining.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter07/06-UsingHashCollisionSeparateChaining.js b/chapter07/06-UsingHashCollisionSeparateChaining.js deleted file mode 100755 index 2a0d3c37..00000000 --- a/chapter07/06-UsingHashCollisionSeparateChaining.js +++ /dev/null @@ -1,40 +0,0 @@ -var hashTableSeparateChaining = new HashTableSeparateChaining(); - -hashTableSeparateChaining.put('Gandalf', 'gandalf@email.com'); -hashTableSeparateChaining.put('John', 'johnsnow@email.com'); -hashTableSeparateChaining.put('Tyrion', 'tyrion@email.com'); -hashTableSeparateChaining.put('Aaron', 'aaron@email.com'); -hashTableSeparateChaining.put('Donnie', 'donnie@email.com'); -hashTableSeparateChaining.put('Ana', 'ana@email.com'); -hashTableSeparateChaining.put('Jonathan', 'jonathan@email.com'); -hashTableSeparateChaining.put('Jamie', 'jamie@email.com'); -hashTableSeparateChaining.put('Sue', 'sue@email.com'); -hashTableSeparateChaining.put('Mindy', 'mindy@email.com'); -hashTableSeparateChaining.put('Paul', 'paul@email.com'); -hashTableSeparateChaining.put('Nathan', 'nathan@email.com'); - -console.log('**** Printing Hash **** '); - -hashTableSeparateChaining.print(); - -console.log('**** Get **** '); - -console.log(hashTableSeparateChaining.get('Jamie')); -console.log(hashTableSeparateChaining.get('Sue')); -console.log(hashTableSeparateChaining.get('Jonathan')); -console.log(hashTableSeparateChaining.get('Loiane')); - -console.log('**** Remove **** '); - -console.log(hashTableSeparateChaining.remove('Gandalf')); -console.log(hashTableSeparateChaining.get('Gandalf')); -hashTableSeparateChaining.print(); - -console.log(hashTableSeparateChaining.remove('Sue')); -hashTableSeparateChaining.print(); - -console.log(hashTableSeparateChaining.remove('Jamie')); -hashTableSeparateChaining.print(); - -console.log(hashTableSeparateChaining.remove('Donnie')); -hashTableSeparateChaining.print(); \ No newline at end of file diff --git a/chapter07/07-HashCollisionLinearProbing.js b/chapter07/07-HashCollisionLinearProbing.js deleted file mode 100644 index 4b1172be..00000000 --- a/chapter07/07-HashCollisionLinearProbing.js +++ /dev/null @@ -1,94 +0,0 @@ -function HashLinearProbing(){ - - var table = []; - - var ValuePair = function(key, value){ - this.key = key; - this.value = value; - - this.toString = function() { - return '[' + this.key + ' - ' + this.value + ']'; - } - }; - - var loseloseHashCode = function (key) { - var hash = 0; - for (var i = 0; i < key.length; i++) { - hash += key.charCodeAt(i); - } - return hash % 37; - }; - - var hashCode = function(key){ - return loseloseHashCode(key); - }; - - this.put = function(key, value){ - var position = hashCode(key); - console.log(position + ' - ' + key); - - if (table[position] == undefined) { - table[position] = new ValuePair(key, value); - } else { - var index = ++position; - while (table[index] != undefined){ - index++; - } - table[index] = new ValuePair(key, value); - } - }; - - this.get = function(key) { - var position = hashCode(key); - - if (table[position] !== undefined){ - if (table[position].key === key) { - return table[position].value; - } else { - var index = ++position; - while (table[index] !== undefined && (table[index] && table[index].key !== key)){ - index++; - } - if (table[index] && table[index].key === key) { - return table[index].value; - } - } - } else { //search for possible deleted value - var index = ++position; - while (table[index] == undefined || index == table.length || - (table[index] !== undefined && table[index] && table[index].key !== key)){ - index++; - } - if (table[index] && table[index].key === key) { - return table[index].value; - } - } - return undefined; - }; - - this.remove = function(key){ - var position = hashCode(key); - - if (table[position] !== undefined){ - if (table[position].key === key) { - table[position] = undefined; - } else { - var index = ++position; - while (table[index] === undefined || table[index].key !== key){ - index++; - } - if (table[index].key === key) { - table[index] = undefined; - } - } - } - }; - - this.print = function() { - for (var i = 0; i < table.length; ++i) { - if (table[i] !== undefined) { - console.log(i + ' -> ' + table[i].toString()); - } - } - }; -} diff --git a/chapter07/08-UsingHashCollisionLinearProbing.html b/chapter07/08-UsingHashCollisionLinearProbing.html deleted file mode 100755 index f5fd9ad5..00000000 --- a/chapter07/08-UsingHashCollisionLinearProbing.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter07/08-UsingHashCollisionLinearProbing.js b/chapter07/08-UsingHashCollisionLinearProbing.js deleted file mode 100644 index 36a33e61..00000000 --- a/chapter07/08-UsingHashCollisionLinearProbing.js +++ /dev/null @@ -1,37 +0,0 @@ -var hashLinearProbing = new HashLinearProbing(); - -hashLinearProbing.put('Gandalf', 'gandalf@email.com'); -hashLinearProbing.put('John', 'johnsnow@email.com'); -hashLinearProbing.put('Tyrion', 'tyrion@email.com'); -hashLinearProbing.put('Aaron', 'aaron@email.com'); -hashLinearProbing.put('Donnie', 'donnie@email.com'); -hashLinearProbing.put('Ana', 'ana@email.com'); -hashLinearProbing.put('Jonathan', 'jonathan@email.com'); -hashLinearProbing.put('Jamie', 'jamie@email.com'); -hashLinearProbing.put('Sue', 'sue@email.com'); -hashLinearProbing.put('Mindy', 'mindy@email.com'); -hashLinearProbing.put('Paul', 'paul@email.com'); -hashLinearProbing.put('Nathan', 'nathan@email.com'); - -console.log('**** Printing Hash **** '); - -hashLinearProbing.print(); - -console.log('**** Get **** '); - -console.log(hashLinearProbing.get('Nathan')); -console.log(hashLinearProbing.get('Loiane')); - -console.log('**** Remove **** '); - -hashLinearProbing.remove('Gandalf'); -console.log(hashLinearProbing.get('Gandalf')); -hashLinearProbing.print(); - -console.log('**** Remove Test 2 **** '); -console.log('Removing Jonathan', hashLinearProbing.remove('Jonathan')); -console.log('**** Print **** '); -hashLinearProbing.print(); -console.log('Get Jamie', hashLinearProbing.get('Jamie')); -console.log('**** Print **** '); -hashLinearProbing.print(); \ No newline at end of file diff --git a/chapter07/09-ES6Map.js b/chapter07/09-ES6Map.js deleted file mode 100644 index 5e0c9dae..00000000 --- a/chapter07/09-ES6Map.js +++ /dev/null @@ -1,17 +0,0 @@ -var map = new Map(); - -map.set('Gandalf', 'gandalf@email.com'); -map.set('John', 'johnsnow@email.com'); -map.set('Tyrion', 'tyrion@email.com'); - -console.log(map.has('Gandalf')); //outputs true -console.log(map.size); //outputs 3 - -console.log(map.keys()); //outputs ["Gandalf", "John", "Tyrion"] -console.log(map.values()); //outputs ["gandalf@email.com", "johnsnow@email.com", "tyrion@email.com"] -console.log(map.get('Tyrion')); //outputs tyrion@email.com - -map.delete('John'); - -console.log(map.keys()); //outputs ["Gandalf", "Tyrion"] -console.log(map.values()); //outputs ["gandalf@email.com", "tyrion@email.com"] \ No newline at end of file diff --git a/chapter07/10-ES6WeakMap.js b/chapter07/10-ES6WeakMap.js deleted file mode 100644 index 8efa16b8..00000000 --- a/chapter07/10-ES6WeakMap.js +++ /dev/null @@ -1,18 +0,0 @@ -var map = new WeakMap(); - -var ob1 = {name:'Gandalf'}, - ob2 = {name:'John'}, - ob3 = {name:'Tyrion'}; - -map.set(ob1, 'gandalf@email.com'); -map.set(ob2, 'johnsnow@email.com'); -map.set(ob3, 'tyrion@email.com'); - -console.log(map.has(ob1)); //outputs true -console.log(map.has(ob2)); //outputs true -console.log(map.has(ob3)); //outputs true - -console.log(map.get(ob3)); //outputs tyrion@email.com - -map.delete(ob2); -console.log(map.has(ob2)); //outputs false diff --git a/chapter07/11-ES6WeakSet.js b/chapter07/11-ES6WeakSet.js deleted file mode 100644 index e54a40de..00000000 --- a/chapter07/11-ES6WeakSet.js +++ /dev/null @@ -1,16 +0,0 @@ -var set = new WeakSet(); - -var ob1 = {name:'Gandalf'}, - ob2 = {name:'John'}, - ob3 = {name:'Tyrion'}; - -set.add(ob1); -set.add(ob2); -set.add(ob3); - -console.log(set.has(ob1)); //outputs true -console.log(set.has(ob2)); //outputs true -console.log(set.has(ob3)); //outputs true - -set.delete(ob2); -console.log(set.has(ob2)); //outputs false diff --git a/chapter08/01-BinarySearchTree.js b/chapter08/01-BinarySearchTree.js deleted file mode 100755 index ae813fce..00000000 --- a/chapter08/01-BinarySearchTree.js +++ /dev/null @@ -1,187 +0,0 @@ -function BinarySearchTree() { - - var Node = function(key){ - this.key = key; - this.left = null; - this.right = null; - }; - - var root = null; - - this.insert = function(key){ - - var newNode = new Node(key); - - //special case - first element - if (root === null){ - root = newNode; - } else { - insertNode(root,newNode); - } - }; - - var insertNode = function(node, newNode){ - if (newNode.key < node.key){ - if (node.left === null){ - node.left = newNode; - } else { - insertNode(node.left, newNode); - } - } else { - if (node.right === null){ - node.right = newNode; - } else { - insertNode(node.right, newNode); - } - } - }; - - this.getRoot = function(){ - return root; - }; - - this.search = function(key){ - - return searchNode(root, key); - }; - - var searchNode = function(node, key){ - - if (node === null){ - return false; - } - - if (key < node.key){ - return searchNode(node.left, key); - - } else if (key > node.key){ - return searchNode(node.right, key); - - } else { //element is equal to node.item - return true; - } - }; - - this.inOrderTraverse = function(callback){ - inOrderTraverseNode(root, callback); - }; - - var inOrderTraverseNode = function (node, callback) { - if (node !== null) { - inOrderTraverseNode(node.left, callback); - callback(node.key); - inOrderTraverseNode(node.right, callback); - } - }; - - this.preOrderTraverse = function(callback){ - preOrderTraverseNode(root, callback); - }; - - var preOrderTraverseNode = function (node, callback) { - if (node !== null) { - callback(node.key); - preOrderTraverseNode(node.left, callback); - preOrderTraverseNode(node.right, callback); - } - }; - - this.postOrderTraverse = function(callback){ - postOrderTraverseNode(root, callback); - }; - - var postOrderTraverseNode = function (node, callback) { - if (node !== null) { - postOrderTraverseNode(node.left, callback); - postOrderTraverseNode(node.right, callback); - callback(node.key); - } - }; - - this.min = function() { - return minNode(root); - }; - - var minNode = function (node) { - if (node){ - while (node && node.left !== null) { - node = node.left; - } - - return node.key; - } - return null; - }; - - this.max = function() { - return maxNode(root); - }; - - var maxNode = function (node) { - if (node){ - while (node && node.right !== null) { - node = node.right; - } - - return node.key; - } - return null; - }; - - this.remove = function(element){ - root = removeNode(root, element); - }; - - var findMinNode = function(node){ - while (node && node.left !== null) { - node = node.left; - } - - return node; - }; - - var removeNode = function(node, element){ - - if (node === null){ - return null; - } - - if (element < node.key){ - node.left = removeNode(node.left, element); - return node; - - } else if (element > node.key){ - node.right = removeNode(node.right, element); - return node; - - } else { //element is equal to node.item - - //handle 3 special conditions - //1 - a leaf node - //2 - a node with only 1 child - //3 - a node with 2 children - - //case 1 - if (node.left === null && node.right === null){ - node = null; - return node; - } - - //case 2 - if (node.left === null){ - node = node.right; - return node; - - } else if (node.right === null){ - node = node.left; - return node; - } - - //case 3 - var aux = findMinNode(node.right); - node.key = aux.key; - node.right = removeNode(node.right, aux.key); - return node; - } - }; -} \ No newline at end of file diff --git a/chapter08/02-UsingBinarySearchTree.html b/chapter08/02-UsingBinarySearchTree.html deleted file mode 100644 index dd40cf48..00000000 --- a/chapter08/02-UsingBinarySearchTree.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter08/02-UsingBinarySearchTree.js b/chapter08/02-UsingBinarySearchTree.js deleted file mode 100644 index eb139837..00000000 --- a/chapter08/02-UsingBinarySearchTree.js +++ /dev/null @@ -1,52 +0,0 @@ -var tree = new BinarySearchTree(); - -tree.insert(11); -tree.insert(7); -tree.insert(15); -tree.insert(5); -tree.insert(3); -tree.insert(9); -tree.insert(8); -tree.insert(10); -tree.insert(13); -tree.insert(12); -tree.insert(14); -tree.insert(20); -tree.insert(18); -tree.insert(25); -tree.insert(6); - -console.log('********* in-order transverse ***********'); -function printNode(value){ - console.log(value); -} -tree.inOrderTraverse(printNode); - -console.log('********* pre-order transverse ***********'); -tree.preOrderTraverse(printNode); - -console.log('********* post-order transverse ***********'); -tree.postOrderTraverse(printNode); - - -console.log('********* max and min ***********'); -console.log(tree.max()); -console.log(tree.min()); -console.log(tree.search(1) ? 'Key 1 found.' : 'Key 1 not found.'); -console.log(tree.search(8) ? 'Key 8 found.' : 'Key 8 not found.'); - - -console.log('********* remove 6 ***********'); -tree.remove(6); -tree.inOrderTraverse(printNode); - -console.log('********* remove 5 ***********'); -tree.remove(5); -tree.inOrderTraverse(printNode); - -console.log('********* remove 15 ***********'); -tree.remove(15); -tree.inOrderTraverse(printNode); - -console.log('********* raw data structure ***********'); -console.log(tree.getRoot()); diff --git a/chapter08/03-AVLTree.js b/chapter08/03-AVLTree.js deleted file mode 100644 index 2eed4f3e..00000000 --- a/chapter08/03-AVLTree.js +++ /dev/null @@ -1,149 +0,0 @@ -function AVLTree() { - - var Node = function(key){ - this.key = key; - this.left = null; - this.right = null; - }; - - var root = null; - - this.getRoot = function(){ - return root; - }; - - var heightNode = function(node) { - if (node === null) { - return -1; - } else { - return Math.max(heightNode(node.left), heightNode(node.right)) + 1; - } - }; - - var rotationLL = function(node) { - var tmp = node.left; - node.left = tmp.right; - tmp.right = node; - - return tmp; - }; - - var rotationRR = function(node) { - var tmp = node.right; - node.right = tmp.left; - tmp.left = node; - - return tmp; - }; - - var rotationLR = function(node) { - node.left = rotationRR(node.left); - return rotationLL(node); - }; - - var rotationRL = function(node) { - node.right = rotationLL(node.right); - return rotationRR(node); - }; - - var insertNode = function(node, element) { - - if (node === null) { - node = new Node(element); - - } else if (element < node.key) { - - node.left = insertNode(node.left, element); - - if (node.left !== null) { - - if ((heightNode(node.left) - heightNode(node.right)) > 1){ - if (element < node.left.key){ - node = rotationLL(node); - } else { - node = rotationLR(node); - } - } - } - } else if (element > node.key) { - - node.right = insertNode(node.right, element); - - if (node.right !== null) { - - if ((heightNode(node.right) - heightNode(node.left)) > 1){ - - if (element > node.right.key){ - node = rotationRR(node); - } else { - node = rotationRL(node); - } - } - } - } - - return node; - }; - - this.insert = function(element) { - root = insertNode(root, element); - }; - - var parentNode; - var nodeToBeDeleted; - - var removeNode = function(node, element) { - if (node === null) { - return null; - } - parentNode = node; - - if (element < node.key) { - node.left = removeNode(node.left, element); - } else { - nodeToBeDeleted = node; - node.right = removeNode(node.right, element); - } - - if (node === parentNode) { //remove node - if (nodeToBeDeleted !== null && element === nodeToBeDeleted.key) { - if (nodeToBeDeleted === parentNode) { - node = node.left; - } else { - var tmp = nodeToBeDeleted.key; - nodeToBeDeleted.key = parentNode.key; - parentNode.key = tmp; - node = node.right; - } - } - } else { //do balancing - - if (node.left === undefined) node.left = null; - if (node.right === undefined) node.right = null; - - if ((heightNode(node.left) - heightNode(node.right)) === 2) { - if (element < node.left.key) { - node = rotationLR(node); - } else { - node = rotationLL(node); - } - } - - if ((heightNode(node.right) - heightNode(node.left)) === 2) { - if (element > node.right.key) { - node = rotationRL(node); - } else { - node = rotationRR(node); - } - } - } - - return node; - }; - - this.remove = function(element) { - parentNode = null; - nodeToBeDeleted = null; - root = removeNode(root, element); - }; -} \ No newline at end of file diff --git a/chapter08/04-UsingAVLTree.html b/chapter08/04-UsingAVLTree.html deleted file mode 100644 index fda15f71..00000000 --- a/chapter08/04-UsingAVLTree.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter08/04-UsingAVLTree.js b/chapter08/04-UsingAVLTree.js deleted file mode 100644 index fd77d395..00000000 --- a/chapter08/04-UsingAVLTree.js +++ /dev/null @@ -1,62 +0,0 @@ -var avlTree = new AVLTree(); - -avlTree.insert(1); -avlTree.insert(2); -avlTree.insert(3); -avlTree.insert(4); -avlTree.insert(5); -avlTree.insert(6); -avlTree.insert(7); -avlTree.insert(14); -avlTree.insert(15); -avlTree.insert(13); -avlTree.insert(12); -avlTree.insert(11); - -//RR rotation -/*avlTree.insert(50); -avlTree.insert(30); -avlTree.insert(70); -avlTree.insert(60); -avlTree.insert(80); -avlTree.insert(90);*/ - -//LL rotation -/*avlTree.insert(50); -avlTree.insert(30); -avlTree.insert(70); -avlTree.insert(10); -avlTree.insert(40); -avlTree.insert(5);*/ - -//LR rotation -/*avlTree.insert(50); -avlTree.insert(30); -avlTree.insert(70); -avlTree.insert(40); -avlTree.insert(10); -avlTree.insert(35);*/ - -//RL rotation -/*avlTree.insert(70); -avlTree.insert(50); -avlTree.insert(80); -avlTree.insert(72); -avlTree.insert(90); -avlTree.insert(75);*/ - -console.log('********* raw data structure ***********'); -console.log(avlTree.getRoot()); - -/*avlTree.remove(12); -avlTree.remove(15); -avlTree.remove(11); -avlTree.remove(14); -avlTree.remove(13); -avlTree.remove(7); -avlTree.remove(6); -avlTree.remove(2); -avlTree.remove(4); - -console.log(avlTree.getRoot());*/ - diff --git a/chapter08/05-RedBlackTree.js b/chapter08/05-RedBlackTree.js deleted file mode 100644 index 7a985d2e..00000000 --- a/chapter08/05-RedBlackTree.js +++ /dev/null @@ -1,101 +0,0 @@ -function RedBlackTree() { - - var Colors = { - RED: 0, - BLACK: 1 - }; - - var Node = function (key, color) { - this.key = key; - this.left = null; - this.right = null; - this.color = color; - - this.flipColor = function(){ - if (this.color === Colors.RED) { - this.color = Colors.BLACK; - } else { - this.color = Colors.RED; - } - }; - }; - - var root = null; - - this.getRoot = function () { - return root; - }; - - var isRed = function(node){ - if (!node){ - return false; - } - return node.color === Colors.RED; - }; - - var flipColors = function(node){ - node.left.flipColor(); - node.right.flipColor(); - }; - - var rotateLeft = function(node){ - var temp = node.right; - if (temp !== null) { - node.right = temp.left; - temp.left = node; - temp.color = node.color; - node.color = Colors.RED; - } - return temp; - }; - - var rotateRight = function (node) { - var temp = node.left; - if (temp !== null) { - node.left = temp.right; - temp.right = node; - temp.color = node.color; - node.color = Colors.RED; - } - return temp; - }; - - var insertNode = function(node, element) { - - if (node === null) { - return new Node(element, Colors.RED); - } - - var newRoot = node; - - if (element < node.key) { - - node.left = insertNode(node.left, element); - - } else if (element > node.key) { - - node.right = insertNode(node.right, element); - - } else { - node.key = element; - } - - if (isRed(node.right) && !isRed(node.left)) { - newRoot = rotateLeft(node); - } - - if (isRed(node.left) && isRed(node.left.left)) { - newRoot = rotateRight(node); - } - if (isRed(node.left) && isRed(node.right)) { - flipColors(node); - } - - return newRoot; - }; - - this.insert = function(element) { - root = insertNode(root, element); - root.color = Colors.BLACK; - }; -} diff --git a/chapter08/06-UsingRedBlackTree.html b/chapter08/06-UsingRedBlackTree.html deleted file mode 100644 index f0fdfcc9..00000000 --- a/chapter08/06-UsingRedBlackTree.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter08/06-UsingRedBlackTree.js b/chapter08/06-UsingRedBlackTree.js deleted file mode 100644 index 31136f99..00000000 --- a/chapter08/06-UsingRedBlackTree.js +++ /dev/null @@ -1,17 +0,0 @@ -var rbTree = new RedBlackTree(); - -rbTree.insert(1); -rbTree.insert(2); -rbTree.insert(3); -rbTree.insert(4); -rbTree.insert(5); -rbTree.insert(6); -rbTree.insert(7); -rbTree.insert(14); -rbTree.insert(15); -rbTree.insert(13); -rbTree.insert(12); -rbTree.insert(11); - -console.log('********* raw data structure ***********'); -console.log(rbTree.getRoot()); \ No newline at end of file diff --git a/chapter09/01-Graph.js b/chapter09/01-Graph.js deleted file mode 100644 index b7a1b847..00000000 --- a/chapter09/01-Graph.js +++ /dev/null @@ -1,172 +0,0 @@ -function Graph() { - - var vertices = []; //list - - var adjList = new Dictionary(); - - this.addVertex = function(v){ - vertices.push(v); - adjList.set(v, []); //initialize adjacency list with array as well; - }; - - this.addEdge = function(v, w){ - adjList.get(v).push(w); - //adjList.get(w).push(v); //commented to run the improved DFS with topological sorting - }; - - this.toString = function(){ - var s = ''; - for (var i=0; i '; - var neighbors = adjList.get(vertices[i]); - for (var j=0; j - - - - - - - - - - - - - \ No newline at end of file diff --git a/chapter09/02-UsingGraphs.js b/chapter09/02-UsingGraphs.js deleted file mode 100755 index 3f143525..00000000 --- a/chapter09/02-UsingGraphs.js +++ /dev/null @@ -1,97 +0,0 @@ -var graph = new Graph(); - -var myVertices = ['A','B','C','D','E','F','G','H','I']; - -for (var i=0; i max){ - max = fTimes[myVertices[i]]; - maxName = myVertices[i]; - } - } - s += ' - ' + maxName; - delete fTimes[maxName]; -} -console.log(s); diff --git a/chapter09/03-ShortestPath.js b/chapter09/03-ShortestPath.js deleted file mode 100644 index cdef7fbb..00000000 --- a/chapter09/03-ShortestPath.js +++ /dev/null @@ -1,76 +0,0 @@ -function ShortestPath(graph) { - - this.graph = graph; - - var INF = Number.MAX_SAFE_INTEGER; - - var minDistance = function(dist, visited){ - - var min = INF, - minIndex = -1; - - for (var v = 0; v < dist.length; v++){ - if (visited[v] == false && dist[v] <= min){ - min = dist[v]; - minIndex = v; - } - } - - return minIndex; - }; - - this.dijkstra = function(src){ - - var dist = [], - visited = [], - length = this.graph.length; - - for (var i = 0; i < length; i++) { - dist[i] = INF; - visited[i] = false; - } - - dist[src] = 0; - - for (var i = 0; i < length-1; i++){ - - var u = minDistance(dist, visited); - - visited[u] = true; - - for (var v = 0; v < length; v++){ - if (!visited[v] && this.graph[u][v]!=0 && dist[u] != INF && dist[u]+this.graph[u][v] < dist[v]){ - dist[v] = dist[u] + this.graph[u][v]; - } - } - } - - return dist; - }; - - this.floydWarshall = function(){ - - var dist = [], - length = this.graph.length, - i, j, k; - - for (i = 0; i < length; i++){ - dist[i] = []; - for (j = 0; j < length; j++){ - dist[i][j] = this.graph[i][j]; - } - } - - for (k = 0; k < length; k++){ - for (i = 0; i < length; i++){ - for (j = 0; j < length; j++){ - if (dist[i][k] + dist[k][j] < dist[i][j]){ - dist[i][j] = dist[i][k] + dist[k][j]; - } - } - } - } - - return dist; - } -} \ No newline at end of file diff --git a/chapter09/04-UsingShortestPathAlgorithms.html b/chapter09/04-UsingShortestPathAlgorithms.html deleted file mode 100644 index 422b9fc4..00000000 --- a/chapter09/04-UsingShortestPathAlgorithms.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter09/04-UsingShortestPathAlgorithms.js b/chapter09/04-UsingShortestPathAlgorithms.js deleted file mode 100644 index 5bc5ac79..00000000 --- a/chapter09/04-UsingShortestPathAlgorithms.js +++ /dev/null @@ -1,45 +0,0 @@ -//adjacent matrix -var i; - -var graph = [[0, 2, 4, 0, 0, 0], - [0, 0, 2, 4, 2, 0], - [0, 0, 0, 0, 3, 0], - [0, 0, 0, 0, 0, 2], - [0, 0, 0, 3, 0, 2], - [0, 0, 0, 0, 0, 0]]; - -var shortestPath = new ShortestPath(graph); - -console.log("********* Dijkstra's Algorithm - Shortest Path ***********"); - -var dist = shortestPath.dijkstra(0); - -for (i = 0; i < dist.length; i++){ - console.log(i + '\t\t' + dist[i]); -} - -console.log("********* Floyd-Warshall Algorithm - All-Pairs Shortest Path ***********"); - -var INF = Number.MAX_SAFE_INTEGER; -graph = [[0, 2, 4, INF, INF, INF], - [INF, 0, 2, 4, 2, INF], - [INF, INF, 0, INF, 3, INF], - [INF, INF, INF, 0, INF, 2], - [INF, INF, INF, 3, 0, 2], - [INF, INF, INF, INF, INF, 0]]; - -shortestPath = new ShortestPath(graph); - -dist = shortestPath.floydWarshall(); - -var s = ''; -for (i=0; i - - - - - - - - - - \ No newline at end of file diff --git a/chapter09/06-UsingMinimumSpanningTree.js b/chapter09/06-UsingMinimumSpanningTree.js deleted file mode 100644 index 286f1dff..00000000 --- a/chapter09/06-UsingMinimumSpanningTree.js +++ /dev/null @@ -1,29 +0,0 @@ -var i; - -var graph = [[0, 2, 4, 0, 0, 0], - [2, 0, 2, 4, 2, 0], - [4, 2, 0, 0, 3, 0], - [0, 4, 0, 0, 3, 2], - [0, 2, 3, 3, 0, 2], - [0, 0, 0, 2, 2, 0]]; - -var mst = new MinimumSpanningTree(graph); - - -console.log("********* Prim's Algorithm - Minimum Spanning Tree ***********"); - -var parent = mst.prim(); - -console.log('Edge Weight'); -for (i = 1; i < graph.length; i++){ - console.log(parent[i] + ' - ' + i + ' ' + graph[i][parent[i]]); -} - -console.log("********* Kruskal Algorithm - Minimum Spanning Tree ***********"); - -parent = mst.kruskal(); - -console.log('Edge Weight'); -for (i = 1; i < graph.length; i++){ - console.log(parent[i] + ' - ' + i + ' ' + graph[i][parent[i]]); -} \ No newline at end of file diff --git a/chapter10/01-SortingSearchingAlgorithms.js b/chapter10/01-SortingSearchingAlgorithms.js deleted file mode 100755 index 916e7403..00000000 --- a/chapter10/01-SortingSearchingAlgorithms.js +++ /dev/null @@ -1,417 +0,0 @@ -function ArrayList(){ - - var array = []; - - this.insert = function(item){ - array.push(item); - }; - - var swap = function(array, index1, index2){ - var aux = array[index1]; - array[index1] = array[index2]; - array[index2] = aux; - //ES2015 swap - Firefox only, for other browser, uncomment code above and coment line below - //[array[index1], array[index2]] = [array[index2], array[index1]]; - }; - - this.toString= function(){ - return array.join(); - }; - - this.array= function(){ - return array; - }; - - this.bubbleSort = function(){ - var length = array.length; - - for (var i=0; i array[j+1]){ - console.log('swap ' + array[j] + ' with ' + array[j+1]); - swap(array, j, j+1); - } - } - } - }; - - this.modifiedBubbleSort = function(){ - var length = array.length; - - for (var i=0; i array[j+1]){ - console.log('swap ' + array[j] + ' with ' + array[j+1]); - swap(j, j+1); - } - } - } - - }; - - this.selectionSort = function(){ - var length = array.length, - indexMin; - - for (var i=0; iarray[j]){ - console.log('new index min ' + array[j]); - indexMin = j; - } - } - if (i !== indexMin){ - console.log('swap ' + array[i] + ' with ' + array[indexMin]); - swap(i, indexMin); - } - } - }; - - this.insertionSort = function(){ - var length = array.length, - j, temp; - for (var i=1; i0 && array[j-1] > temp){ - console.log('shift ' + array[j-1]); - array[j] = array[j-1]; - j--; - } - console.log('insert ' + temp); - array[j] = temp; - } - }; - - var insertionSort_ = function(array){ - var length = array.length, - j, temp; - for (var i=1; i0 && array[j-1] > temp){ - array[j] = array[j-1]; - j--; - } - array[j] = temp; - } - }; - - this.mergeSort = function(){ - array = mergeSortRec(array); - }; - - var mergeSortRec = function(array){ - - var length = array.length; - - if(length === 1) { - console.log(array); - return array; - } - - var mid = Math.floor(length / 2), - left = array.slice(0, mid), - right = array.slice(mid, length); - - return merge(mergeSortRec(left), mergeSortRec(right)); - }; - - var merge = function(left, right){ - var result = [], - il = 0, - ir = 0; - - while(il < left.length && ir < right.length) { - - if(left[il] < right[ir]) { - result.push(left[il++]); - } else{ - result.push(right[ir++]); - } - } - - while (il < left.length){ - result.push(left[il++]); - } - - while (ir < right.length){ - result.push(right[ir++]); - } - - console.log(result); - - return result; - }; - - this.quickSort = function(){ - quick(array, 0, array.length - 1); - }; - - var partition = function(array, left, right) { - - var pivot = array[Math.floor((right + left) / 2)], - i = left, - j = right; - - console.log('pivot is ' + pivot + '; left is ' + left + '; right is ' + right); - - while (i <= j) { - while (array[i] < pivot) { - i++; - console.log('i = ' + i); - } - - while (array[j] > pivot) { - j--; - console.log('j = ' + j); - } - - if (i <= j) { - console.log('swap ' + array[i] + ' with ' + array[j]); - swap(array, i, j); - i++; - j--; - } - } - - return i; - }; - - var quick = function(array, left, right){ - - var index; - - if (array.length > 1) { - - index = partition(array, left, right); - - if (left < index - 1) { - quick(array, left, index - 1); - } - - if (index < right) { - quick(array, index, right); - } - } - return array; - }; - - this.heapSort = function(){ - var heapSize = array.length; - - buildHeap(array); - - while (heapSize > 1) { - heapSize--; - console.log('swap (' + + array[0] + ',' + array[heapSize] + ')'); - swap(array, 0, heapSize); - console.log('heapify ' + array.join()); - heapify(array, heapSize, 0); - } - }; - - var buildHeap = function(array){ - console.log('building heap'); - var heapSize = array.length; - for (var i = Math.floor(array.length / 2); i >= 0; i--) { - heapify(array, heapSize, i); - } - console.log('heap created: ' + array.join()); - }; - - var heapify = function(array, heapSize, i){ - var left = i * 2 + 1, - right = i * 2 + 2, - largest = i; - - if (left < heapSize && array[left] > array[largest]) { - largest = left; - } - - if (right < heapSize && array[right] > array[largest]) { - largest = right; - } - - console.log('Heapify Index = '+ i + ' and Heap Size = ' + heapSize); - - if (largest !== i) { - console.log('swap index ' + i + ' with ' + largest + ' (' + + array[i] + ',' + array[largest] + ')'); - swap(array, i, largest); - console.log('heapify ' + array.join()); - heapify(array, heapSize, largest); - } - }; - - this.countingSort = function(){ - - var i, - maxValue = this.findMaxValue(), - sortedIndex = 0, - counts = new Array(maxValue + 1); - - for (i = 0; i < array.length; i++) { - if (!counts[array[i]]) { - counts[array[i]] = 0; - } - counts[array[i]]++; - } - - console.log('Frequencies: ' + counts.join()); - - for (i = 0; i < counts.length; i++) { - while (counts[i] > 0) { - array[sortedIndex++] = i; - counts[i]--; - } - } - }; - - this.bucketSort = function(bucketSize){ - - var i, - minValue = this.findMinValue(), - maxValue = this.findMaxValue(), - BUCKET_SIZE = 5; - - console.log('minValue ' + minValue); - console.log('maxValue ' + maxValue); - - bucketSize = bucketSize || BUCKET_SIZE; - var bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1; - var buckets = new Array(bucketCount); - console.log('bucketSize = ' + bucketCount); - for (i = 0; i < buckets.length; i++) { - buckets[i] = []; - } - - for (i = 0; i < array.length; i++) { - buckets[Math.floor((array[i] - minValue) / bucketSize)].push(array[i]); - console.log('pushing item ' + array[i] + ' to bucket index ' + Math.floor((array[i] - minValue) / bucketSize)); - } - - array = []; - for (i = 0; i < buckets.length; i++) { - insertionSort_(buckets[i]); - - console.log('bucket sorted ' + i + ': ' + buckets[i].join()); - - for (var j = 0; j < buckets[i].length; j++) { - array.push(buckets[i][j]); - } - } - }; - - this.radixSort = function(radixBase){ - - var i, - minValue = this.findMinValue(), - maxValue = this.findMaxValue(), - radixBase = radixBase || 10; - - // Perform counting sort for each significant digit), starting at 1 - var significantDigit = 1; - while (((maxValue - minValue) / significantDigit) >= 1) { - console.log('radix sort for digit ' + significantDigit); - array = countingSortForRadix(array, radixBase, significantDigit, minValue); - console.log(array.join()); - significantDigit *= radixBase; - } - }; - - var countingSortForRadix = function(array, radixBase, significantDigit, minValue){ - var i, countsIndex, - counts = new Array(radixBase), - aux = new Array(radixBase); - - for (i = 0; i < radixBase; i++) { - counts[i] = 0; - } - - for (i = 0; i < array.length; i++) { - countsIndex = Math.floor(((array[i] - minValue) / significantDigit) % radixBase); - counts[countsIndex]++; - } - - for (i = 1; i < radixBase; i++) { - counts[i] += counts[i - 1]; - } - - for (i = array.length - 1; i >= 0; i--) { - countsIndex = Math.floor(((array[i] - minValue) / significantDigit) % radixBase); - aux[--counts[countsIndex]] = array[i]; - } - - for (i = 0; i < array.length; i++) { - array[i] = aux[i]; - } - - return array; - }; - - this.sequentialSearch = function(item){ - - for (var i=0; i array[i]){ - min = array[i]; - } - } - - return min; - }; - - this.binarySearch = function(item){ - this.quickSort(); - - var low = 0, - high = array.length - 1, - mid, element; - - while (low <= high){ - mid = Math.floor((low + high) / 2); - element = array[mid]; - console.log('mid element is ' + element); - if (element < item) { - low = mid + 1; - console.log('low is ' + low); - } else if (element > item) { - high = mid - 1; - console.log('high is ' + high); - } else { - console.log('found it'); - return mid; - } - } - return -1; - }; - -} \ No newline at end of file diff --git a/chapter10/02-UsingSortingAlgorithms.html b/chapter10/02-UsingSortingAlgorithms.html deleted file mode 100755 index 7a666fdb..00000000 --- a/chapter10/02-UsingSortingAlgorithms.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter10/02-UsingSortingAlgorithms.js b/chapter10/02-UsingSortingAlgorithms.js deleted file mode 100755 index 92b63e8f..00000000 --- a/chapter10/02-UsingSortingAlgorithms.js +++ /dev/null @@ -1,126 +0,0 @@ -function createNonSortedArray(size){ - var array = new ArrayList(); - - for (var i = size; i> 0; i--){ - array.insert(i); - } - - return array; -} - -function createRandomNonSortedArray(){ - var array = new ArrayList(); - - array.insert(3); - array.insert(5); - array.insert(1); - array.insert(6); - array.insert(4); - array.insert(7); - array.insert(2); - - return array; -} - -function printArray(array){ - console.log(array.toString()); -} - -function createNonSortedArrayAndPrint(size){ - var array = createNonSortedArray(size); - printArray(array); - - return array; -} - -console.log('********** Bubble Sort **********'); - -var array = createNonSortedArrayAndPrint(5); - -array.bubbleSort(); - -printArray(array); - -console.log('********** Modified Bubble Sort **********'); - -array = createNonSortedArrayAndPrint(5); - -array.modifiedBubbleSort(); - -printArray(array); - -console.log('********** Selection Sort **********'); - -array = createNonSortedArrayAndPrint(5); - -array.selectionSort(); - -printArray(array); - -console.log('********** Insertion Sort **********'); - -array = createNonSortedArrayAndPrint(5); - -array.insertionSort(); - -printArray(array); - -console.log('********** Merge Sort **********'); - -array = createNonSortedArrayAndPrint(8); - -array.mergeSort(); - -printArray(array); - -console.log('********** Quick Sort **********'); -array = createRandomNonSortedArray(); - -printArray(array); - -array.quickSort(); - -printArray(array); - -console.log('********** Heap Sort **********'); -array = createRandomNonSortedArray(); - -printArray(array); - -array.heapSort(); - -printArray(array); - - -console.log('********** Counting Sort **********'); - -array = createNonSortedArrayAndPrint(8); - -array.countingSort(); - -printArray(array); - -console.log('********** Bucket Sort **********'); - -array = createNonSortedArrayAndPrint(8); - -array.bucketSort(3); - -printArray(array); - -console.log('********** Radix Sort **********'); - -var array = new ArrayList(); - -array.insert(30); -array.insert(52); -array.insert(13); -array.insert(25); -array.insert(31); -array.insert(23); -array.insert(2); - -array.radixSort(); - -console.log('Result: '); -printArray(array); diff --git a/chapter10/03-UsingSearchingAlgorithms.html b/chapter10/03-UsingSearchingAlgorithms.html deleted file mode 100755 index a4e4b6a3..00000000 --- a/chapter10/03-UsingSearchingAlgorithms.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/chapter10/03-UsingSearchingAlgorithms.js b/chapter10/03-UsingSearchingAlgorithms.js deleted file mode 100755 index 62201e80..00000000 --- a/chapter10/03-UsingSearchingAlgorithms.js +++ /dev/null @@ -1,33 +0,0 @@ -function createNonSortedArray(items){ - var array = new ArrayList(); - - for (var i = items; i> 0; i--){ - array.insert(i); - } - - return array; -} - -var array = createNonSortedArray(5); - -console.log('********** Sequential Sort #3 **********'); - -console.log(array.sequentialSearch(3)); - -console.log('********** Min **********'); - -console.log(array.findMinValue()); - -console.log('********** Max **********'); - -console.log(array.findMaxValue()); - -console.log('********** Binary Search #3 **********'); - -console.log(array.binarySearch(3)); - -console.log('********** Binary Search #2 **********'); - -var array = createNonSortedArray(8); - -console.log(array.binarySearch(2)); \ No newline at end of file diff --git a/chapter11/01-Recursion.html b/chapter11/01-Recursion.html deleted file mode 100755 index 5961583b..00000000 --- a/chapter11/01-Recursion.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/01-Recursion.js b/chapter11/01-Recursion.js deleted file mode 100755 index bd16253d..00000000 --- a/chapter11/01-Recursion.js +++ /dev/null @@ -1,25 +0,0 @@ -//Recursive solution - DP -function fibonacci(num){ - if (num === 1 || num === 2){ - return 1; - } - if (num > 2){ - return fibonacci(num - 1) + fibonacci(num - 2); - } -} - -//Non Recursive solution -function fib(num){ - var n1 = 1, - n2 = 1, - n = 1; - for (var i = 3; i<=num; i++){ - n = n1 + n2; - n1 = n2; - n2 = n; - } - return n; -} - -console.log(fibonacci(6)); -console.log(fib(6)); \ No newline at end of file diff --git a/chapter11/02-InfiniteRecursion.html b/chapter11/02-InfiniteRecursion.html deleted file mode 100755 index e51a8132..00000000 --- a/chapter11/02-InfiniteRecursion.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/02-InfiniteRecursion.js b/chapter11/02-InfiniteRecursion.js deleted file mode 100755 index 2ca26d33..00000000 --- a/chapter11/02-InfiniteRecursion.js +++ /dev/null @@ -1,15 +0,0 @@ -var i = 0; - -function recursiveFn () { - i++; - recursiveFn(); -} - -try { - recursiveFn(); -} catch (ex) { - alert('i = ' + i + ' error: ' + ex); -} - -//chrome 37 = 20955 RangeError: Maximum call stack size exceeded -//ff 27 = 343429 InternalError: too much recursion \ No newline at end of file diff --git a/chapter11/03-MinCoinChangeDP.html b/chapter11/03-MinCoinChangeDP.html deleted file mode 100755 index c4171470..00000000 --- a/chapter11/03-MinCoinChangeDP.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/03-MinCoinChangeDP.js b/chapter11/03-MinCoinChangeDP.js deleted file mode 100644 index 90a4a541..00000000 --- a/chapter11/03-MinCoinChangeDP.js +++ /dev/null @@ -1,38 +0,0 @@ -function MinCoinChange(coins){ - - var cache = {}; - - this.makeChange = function(amount) { - var me = this; - if (!amount) { - return []; - } - if (cache[amount]) { - return cache[amount]; - } - var min = [], newMin, newAmount; - for (var i=0; i= 0){ - newMin = me.makeChange(newAmount); - } - if ( - newAmount >= 0 && - (newMin.length < min.length-1 || !min.length) && - (newMin.length || !newAmount) - ){ - min = [coin].concat(newMin); - console.log('new Min ' + min + ' for ' + amount); - } - } - return (cache[amount] = min); - }; -} - - -var minCoinChange = new MinCoinChange([1, 5, 10, 25]); -console.log(minCoinChange.makeChange(36)); - -var minCoinChange2 = new MinCoinChange([1, 3, 4]); -console.log(minCoinChange2.makeChange(6)); \ No newline at end of file diff --git a/chapter11/04-MinCoinChangeGreedy.html b/chapter11/04-MinCoinChangeGreedy.html deleted file mode 100755 index cc01ddc2..00000000 --- a/chapter11/04-MinCoinChangeGreedy.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/04-MinCoinChangeGreedy.js b/chapter11/04-MinCoinChangeGreedy.js deleted file mode 100644 index 3050f7ed..00000000 --- a/chapter11/04-MinCoinChangeGreedy.js +++ /dev/null @@ -1,25 +0,0 @@ -function MinCoinChange(coins){ - - var coins = coins; - - var cache = {}; - - this.makeChange = function(amount) { - var change = [], - total = 0; - for (var i=coins.length; i>=0; i--){ - var coin = coins[i]; - while (total + coin <= amount) { - change.push(coin); - total += coin; - } - } - return change; - }; -} - -var minCoinChange = new MinCoinChange([1, 5, 10, 25]); -console.log(minCoinChange.makeChange(36)); - -var minCoinChange2 = new MinCoinChange([1, 3, 4]); -console.log(minCoinChange2.makeChange(6)); \ No newline at end of file diff --git a/chapter11/05-KnapsackProblemDP.html b/chapter11/05-KnapsackProblemDP.html deleted file mode 100644 index 316f9722..00000000 --- a/chapter11/05-KnapsackProblemDP.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/05-KnapsackProblemDP.js b/chapter11/05-KnapsackProblemDP.js deleted file mode 100644 index fb6adbe7..00000000 --- a/chapter11/05-KnapsackProblemDP.js +++ /dev/null @@ -1,53 +0,0 @@ -function knapSack(capacity, weights, values, n) { - - var i, w, a, b, kS = []; - - for (i = 0; i <= n; i++) { - kS[i] = []; - } - - for (i = 0; i <= n; i++){ - for (w = 0; w <= capacity; w++){ - if (i == 0 || w == 0){ - kS[i][w] = 0; - - } else if (weights[i-1] <= w){ - a = values[i-1] + kS[i-1][w-weights[i-1]]; - b = kS[i-1][w]; - kS[i][w] = (a > b) ? a : b; //max(a,b) - console.log(a + ' can be part of the solution'); - } else{ - kS[i][w] = kS[i-1][w]; - } - } - console.log(kS[i].join()); - } - - //extra algorithm to find the items that are part of the solution - findValues(n, capacity, kS, values, weights); - - return kS[n][capacity]; -} - -function findValues(n, capacity, kS, weights, values){ - var i=n, k=capacity; - - console.log('Items that are part of the solution:'); - - while (i>0 && k>0){ - if (kS[i][k] !== kS[i-1][k]){ - console.log('item '+i+' can be part of solution w,v: ' + weights[i-1] + ',' + values[i-1]); - i--; - k = k - kS[i][k]; - } else { - i--; - } - } -} - -var values = [3,4,5], - weights = [2,3,4], - capacity = 5, - n = values.length; - -console.log('Total value that can be carried: ' + knapSack(capacity, weights, values, n)); \ No newline at end of file diff --git a/chapter11/06-KnapSackProblemRecursive.html b/chapter11/06-KnapSackProblemRecursive.html deleted file mode 100644 index cc000756..00000000 --- a/chapter11/06-KnapSackProblemRecursive.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/06-KnapSackProblemRecursive.js b/chapter11/06-KnapSackProblemRecursive.js deleted file mode 100644 index 583092e1..00000000 --- a/chapter11/06-KnapSackProblemRecursive.js +++ /dev/null @@ -1,22 +0,0 @@ -function knapSack(capacity, weights, values, n) { - - if (n == 0 || capacity == 0){ - return 0; - } - - if (weights[n-1] > capacity){ - return knapSack(capacity, weights, values, n-1); - - } else { - var a = values[n-1] + knapSack(capacity-weights[n-1], weights, values, n-1), - b = knapSack(capacity, weights, values, n-1); - return (a > b) ? a : b; - } -} - -var values = [3,4,5], - weights = [2,3,4], - capacity = 5, - n = values.length; - -console.log(knapSack(capacity, weights, values, n)); \ No newline at end of file diff --git a/chapter11/07-KnapSackProblemGreedy.html b/chapter11/07-KnapSackProblemGreedy.html deleted file mode 100644 index 227d7b4b..00000000 --- a/chapter11/07-KnapSackProblemGreedy.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/07-KnapSackProblemGreedy.js b/chapter11/07-KnapSackProblemGreedy.js deleted file mode 100644 index 4c12e1a6..00000000 --- a/chapter11/07-KnapSackProblemGreedy.js +++ /dev/null @@ -1,28 +0,0 @@ -function knapSack(capacity, values, weights) { - var n = values.length, - load = 0, - i = 0, - val = 0; - - for (i=0; i - - - - - - - - - \ No newline at end of file diff --git a/chapter11/08-LongestCommonSubsequenceDP.js b/chapter11/08-LongestCommonSubsequenceDP.js deleted file mode 100644 index b5eaf3f1..00000000 --- a/chapter11/08-LongestCommonSubsequenceDP.js +++ /dev/null @@ -1,105 +0,0 @@ -function lcs(wordX, wordY) { - - var m = wordX.length, - n = wordY.length, - l = [], - i, j, a, b; - - for (i = 0; i <= m; ++i) { - l[i] = []; - for (j = 0; j <= n; ++j) { - l[i][j] = 0; - } - } - - for (i=0; i<=m; i++) { - for (j=0; j<=n; j++) { - if (i == 0 || j == 0){ - l[i][j] = 0; - - } else if (wordX[i-1] == wordY[j-1]) { - l[i][j] = l[i-1][j-1] + 1; - - } else { - a = l[i-1][j]; - b = l[i][j-1]; - l[i][j] = (a > b) ? a : b; //max(a,b) - } - } - console.log(l[i].join()); - } - - return l[m][n]; -} - -//complete algorithm that prints the LCS as well - -function lcs2(wordX, wordY) { - - var m = wordX.length, - n = wordY.length, - l = [], - solution = [], - i, j, a, b; - - for (i = 0; i <= m; ++i) { - l[i] = []; - solution[i] = []; - for (j = 0; j <= n; ++j) { - l[i][j] = 0; - solution[i][j] = '0'; - } - } - - for (i=0; i<=m; i++) { - for (j=0; j<=n; j++) { - if (i == 0 || j == 0){ - l[i][j] = 0; - - } else if (wordX[i-1] == wordY[j-1]) { - l[i][j] = l[i-1][j-1] + 1; - solution[i][j] = 'diagonal'; - - } else { - a = l[i-1][j]; - b = l[i][j-1]; - l[i][j] = (a > b) ? a : b; //max(a,b) - - solution[i][j] = (l[i][j] == l[i - 1][j]) ? 'top' : 'left'; - } - } - console.log(l[i].join()); - console.log(solution[i].join()); - } - - printSolution(solution, l, wordX, wordY, m, n); - - return l[m][n]; -} - -function printSolution(solution, l, wordX, wordY, m, n){ - - var a = m, b = n, i, j, - x = solution[a][b], - answer = ''; - - while (x !== '0') { - if (solution[a][b] === 'diagonal') { - answer = wordX[a - 1] + answer; - a--; - b--; - } else if (solution[a][b] === 'left') { - b--; - } else if (solution[a][b] === 'top') { - a--; - } - x = solution[a][b]; - } - - console.log('lcs: '+ answer); -} - -var wordX = 'acbaed', - wordY = 'abcadf'; - -console.log(lcs2(wordX, wordY)); \ No newline at end of file diff --git a/chapter11/09-LongestCommonSubsequenceRecursive.html b/chapter11/09-LongestCommonSubsequenceRecursive.html deleted file mode 100644 index 59573751..00000000 --- a/chapter11/09-LongestCommonSubsequenceRecursive.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/09-LongestCommonSubsequenceRecursive.js b/chapter11/09-LongestCommonSubsequenceRecursive.js deleted file mode 100644 index 1c96fab1..00000000 --- a/chapter11/09-LongestCommonSubsequenceRecursive.js +++ /dev/null @@ -1,19 +0,0 @@ -function lcs(wordwordX, wordwordY, m, n) { - - if (m == 0 || n == 0){ - return 0; - } - - if (wordwordX[m-1] == wordY[n-1]){ - return 1 + lcs(wordX, wordY, m-1, n-1); - } else { - var a = lcs(wordX, wordY, m, n-1), - b = lcs(wordX, wordY, m-1, n); - return (a > b) ? a : b; - } -} - -var wordX = 'acbaed', - wordY = 'abcadf'; - -console.log(lcs(wordX, wordY, wordX.length, wordY.length)); \ No newline at end of file diff --git a/chapter11/10-MatrixChainMultiplicationDP.html b/chapter11/10-MatrixChainMultiplicationDP.html deleted file mode 100644 index 2108a100..00000000 --- a/chapter11/10-MatrixChainMultiplicationDP.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/chapter11/10-MatrixChainMultiplicationDP.js b/chapter11/10-MatrixChainMultiplicationDP.js deleted file mode 100644 index e335b3cc..00000000 --- a/chapter11/10-MatrixChainMultiplicationDP.js +++ /dev/null @@ -1,56 +0,0 @@ -function matrixChainOrder(p, n) { - - var i, j, k, l, q, - m = [], s=[]; - - for (i = 1; i <= n; i++){ - m[i] = []; - m[i][i] = 0; - - } - - for (i = 0; i <= n; i++){ //to help printing the optimal solution - s[i] = []; //auxiliary - for (j=0; j<=n; j++){ - s[i][j] = 0; - } - } - - for (l=2; l - - - - - - - - - \ No newline at end of file diff --git a/chapter11/11-MatrixChainMultiplicationRecursive.js b/chapter11/11-MatrixChainMultiplicationRecursive.js deleted file mode 100644 index 0b327524..00000000 --- a/chapter11/11-MatrixChainMultiplicationRecursive.js +++ /dev/null @@ -1,26 +0,0 @@ -function matrixChainOrder(p, i, j){ - - if(i == j) { - return 0; - } - - var k, count, - min = Number.MAX_SAFE_INTEGER; - - for (k = i; k - - - - - - - - - \ No newline at end of file diff --git a/examples/PacktDataStructuresAlgorithms.min.js b/examples/PacktDataStructuresAlgorithms.min.js new file mode 100644 index 00000000..b7d4c0c6 --- /dev/null +++ b/examples/PacktDataStructuresAlgorithms.min.js @@ -0,0 +1,2 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("PacktDataStructuresAlgorithms",[],t):"object"==typeof exports?exports.PacktDataStructuresAlgorithms=t():e.PacktDataStructuresAlgorithms=t()}(window,function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{configurable:!1,enumerable:!0,get:r})},n.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=66)}([function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.lesserEquals=function(e,n,r){var i=r(e,n);return i===t.LESS_THAN||i===t.EQUALS},e.biggerEquals=function(e,n,r){var i=r(e,n);return i===t.BIGGER_THAN||i===t.EQUALS},e.defaultCompare=function(e,n){return e===n?t.EQUALS:e0&&void 0!==arguments[0]?arguments[0]:n.defaultEquals;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.equalsFn=t,this.count=0,this.head=void 0}return i(e,[{key:"push",value:function(e){var t=new r.Node(e),n=void 0;if(null==this.head)this.head=t;else{for(n=this.head;null!=n.next;)n=n.next;n.next=t}this.count++}},{key:"getElementAt",value:function(e){if(e>=0&&e<=this.count){for(var t=this.head,n=0;n=0&&t<=this.count){var n=new r.Node(e);if(0===t){var i=this.head;n.next=i,this.head=n}else{var o=this.getElementAt(t-1);n.next=o.next,o.next=n}return this.count++,!0}return!1}},{key:"removeAt",value:function(e){if(e>=0&&e1&&(u=function(e,n,r,i){for(var o=e[Math.floor((r+n)/2)],u=n,a=r;u<=a;){for(;i(e[u],o)===t.Compare.LESS_THAN;)u++;for(;i(e[a],o)===t.Compare.BIGGER_THAN;)a--;u<=a&&((0,t.swap)(e,u,a),u++,a--)}return u}(e,r,i,o),r1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare;return n(e,0,e.length-1,r)}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(0)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.findMaxValue=function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare;if(e&&e.length>0){for(var r=e[0],i=1;i1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare;if(e&&e.length>0){for(var r=e[0],i=1;i1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare,r=e.length,i=void 0,o=1;o0&&n(e[u-1],i)===t.Compare.BIGGER_THAN;)e[u]=e[u-1],u--;e[u]=i}return e}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var t=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultCompare;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.compareFn=t,this.root=void 0}return i(e,[{key:"insert",value:function(e){null==this.root?this.root=new r.Node(e):this.insertNode(this.root,e)}},{key:"insertNode",value:function(e,t){this.compareFn(t,e.key)===n.Compare.LESS_THAN?null==e.left?e.left=new r.Node(t):this.insertNode(e.left,t):null==e.right?e.right=new r.Node(t):this.insertNode(e.right,t)}},{key:"getRoot",value:function(){return this.root}},{key:"search",value:function(e){return this.searchNode(this.root,e)}},{key:"searchNode",value:function(e,t){return null!=e&&(this.compareFn(t,e.key)===n.Compare.LESS_THAN?this.searchNode(e.left,t):this.compareFn(t,e.key)!==n.Compare.BIGGER_THAN||this.searchNode(e.right,t))}},{key:"inOrderTraverse",value:function(e){this.inOrderTraverseNode(this.root,e)}},{key:"inOrderTraverseNode",value:function(e,t){null!=e&&(this.inOrderTraverseNode(e.left,t),t(e.key),this.inOrderTraverseNode(e.right,t))}},{key:"preOrderTraverse",value:function(e){this.preOrderTraverseNode(this.root,e)}},{key:"preOrderTraverseNode",value:function(e,t){null!=e&&(t(e.key),this.preOrderTraverseNode(e.left,t),this.preOrderTraverseNode(e.right,t))}},{key:"postOrderTraverse",value:function(e){this.postOrderTraverseNode(this.root,e)}},{key:"postOrderTraverseNode",value:function(e,t){null!=e&&(this.postOrderTraverseNode(e.left,t),this.postOrderTraverseNode(e.right,t),t(e.key))}},{key:"min",value:function(){return this.minNode(this.root)}},{key:"minNode",value:function(e){for(var t=e;null!=t&&null!=t.left;)t=t.left;return t}},{key:"max",value:function(){return this.maxNode(this.root)}},{key:"maxNode",value:function(e){for(var t=e;null!=t&&null!=t.right;)t=t.right;return t}},{key:"remove",value:function(e){this.root=this.removeNode(this.root,e)}},{key:"removeNode",value:function(e,t){if(null!=e){if(this.compareFn(t,e.key)===n.Compare.LESS_THAN)return e.left=this.removeNode(e.left,t),e;if(this.compareFn(t,e.key)===n.Compare.BIGGER_THAN)return e.right=this.removeNode(e.right,t),e;if(null==e.left&&null==e.right)return e=void 0;if(null==e.left)return e=e.right;if(null==e.right)return e=e.left;var r=this.minNode(e.right);return e.key=r.key,e.right=this.removeNode(e.right,r.key),e}}}]),e}();t.default=o,e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t,n(0),n(1)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultToString;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.toStrFn=t,this.table={}}return i(e,[{key:"set",value:function(e,t){if(null!=e&&null!=t){var n=this.toStrFn(e);return this.table[n]=new r.ValuePair(e,t),!0}return!1}},{key:"get",value:function(e){var t=this.table[this.toStrFn(e)];return null==t?void 0:t.value}},{key:"hasKey",value:function(e){return null!=this.table[this.toStrFn(e)]}},{key:"remove",value:function(e){return!!this.hasKey(e)&&(delete this.table[this.toStrFn(e)],!0)}},{key:"values",value:function(){return this.keyValues().map(function(e){return e.value})}},{key:"keys",value:function(){return this.keyValues().map(function(e){return e.key})}},{key:"keyValues",value:function(){return Object.values(this.table)}},{key:"forEach",value:function(e){for(var t=this.keyValues(),n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultEquals;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var r=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return r.tail=void 0,r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),a(t,[{key:"push",value:function(e){var t=new i.DoublyNode(e);null==this.head?(this.head=t,this.tail=t):(this.tail.next=t,t.prev=this.tail,this.tail=t),this.count++}},{key:"insert",value:function(e,t){if(t>=0&&t<=this.count){var n=new i.DoublyNode(e),r=this.head;if(0===t)null==this.head?(this.head=n,this.tail=n):(n.next=this.head,this.head.prev=n,this.head=n);else if(t===this.count)(r=this.tail).next=n,n.prev=r,this.tail=n;else{var o=this.getElementAt(t-1);r=o.next,n.next=r,o.next=n,r.prev=n,n.prev=o}return this.count++,!0}return!1}},{key:"removeAt",value:function(e){if(e>=0&&e0)this.lowestCount--,this.items[this.lowestCount]=e;else{for(var t=this.count;t>0;t--)this.items[t]=this.items[t-1];this.count++,this.items[0]=e}}},{key:"addBack",value:function(e){this.items[this.count]=e,this.count++}},{key:"removeFront",value:function(){if(!this.isEmpty()){var e=this.items[this.lowestCount];return delete this.items[this.lowestCount],this.lowestCount++,e}}},{key:"removeBack",value:function(){if(!this.isEmpty()){this.count--;var e=this.items[this.count];return delete this.items[this.count],e}}},{key:"peekFront",value:function(){if(!this.isEmpty())return this.items[this.lowestCount]}},{key:"peekBack",value:function(){if(!this.isEmpty())return this.items[this.count-1]}},{key:"isEmpty",value:function(){return 0===this.size()}},{key:"clear",value:function(){this.items={},this.count=0,this.lowestCount=0}},{key:"size",value:function(){return this.count-this.lowestCount}},{key:"toString",value:function(){if(this.isEmpty())return"";for(var e=""+this.items[this.lowestCount],t=this.lowestCount+1;t=0&&n>=0&&t1&&void 0!==arguments[1]?arguments[1]:1,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.length-1;if(n===r)return 0;for(var i=Number.MAX_SAFE_INTEGER,o=n;o2&&void 0!==arguments[2]?arguments[2]:t.length,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:n.length;if(0===r||0===i)return 0;if(t[r-1]===n[i-1])return 1+e(t,n,r-1,i-1);var o=e(t,n,r,i-1),u=e(t,n,r-1,i);return o>u?o:u}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.lcs=function(e,t){for(var n=e.length,r=t.length,i=[],o=[],u=0;u<=n;u++){i[u]=[],o[u]=[];for(var a=0;a<=r;a++)i[u][a]=0,o[u][a]="0"}for(var f=0;f<=n;f++)for(var l=0;l<=r;l++)if(0===f||0===l)i[f][l]=0;else if(e[f-1]===t[l-1])i[f][l]=i[f-1][l-1]+1,o[f][l]="diagonal";else{var s=i[f-1][l],c=i[f][l-1];i[f][l]=s>c?s:c,o[f][l]=i[f][l]===i[f-1][l]?"top":"left"}return function(e,t,n,r){for(var i=n,o=r,u=e[i][o],a="";"0"!==u;)"diagonal"===e[i][o]?(a=t[i-1]+a,i--,o--):"left"===e[i][o]?o--:"top"===e[i][o]&&i--,u=e[i][o];return a}(o,e,n,r)}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.lcs=function(e,t){for(var n=e.length,r=t.length,i=[],o=0;o<=n;o++){i[o]=[];for(var u=0;u<=r;u++)i[o][u]=0}for(var a=0;a<=n;a++)for(var f=0;f<=r;f++)if(0===a||0===f)i[a][f]=0;else if(e[a-1]===t[f-1])i[a][f]=i[a-1][f-1]+1;else{var l=i[a-1][f],s=i[a][f-1];i[a][f]=l>s?l:s}return i[n][r]}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.knapSack=function(e,t,n){for(var r=n.length,i=0,o=0,u=0;ut)return e(t,n,r,i-1);var o=r[i-1]+e(t-n[i-1],n,r,i-1),u=e(t,n,r,i-1);return o>u?o:u}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.knapSack=function(e,t,n,r){for(var i=[],o=0;o<=r;o++)i[o]=[];for(var u=0;u<=r;u++)for(var a=0;a<=e;a++)if(0===u||0===a)i[u][a]=0;else if(t[u-1]<=a){var f=n[u-1]+i[u-1][a-t[u-1]],l=i[u-1][a];i[u][a]=f>l?f:l}else i[u][a]=i[u-1][a];return function(e,t,n){for(var r=e,i=t;r>0&&i>0;)n[r][i]!==n[r-1][i]?i-=n[--r][i]:r--}(r,e,i),i[r][e]}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.minCoinChange=function(e,t){for(var n=[],r=0,i=e.length;i>=0;i--)for(var o=e[i];r+o<=t;)n.push(o),r+=o;return n}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.minCoinChange=function(e,t){var n=[];return function t(r){if(!r)return[];if(n[r])return n[r];for(var i=[],o=void 0,u=void 0,a=0;a=0&&(o=t(u)),u>=0&&(o.length2&&void 0!==arguments[2]?arguments[2]:t.defaultCompare,o=(0,n.quickSort)(e).length-1;return function e(n,r,i,o){var u=arguments.length>4&&void 0!==arguments[4]?arguments[4]:t.defaultCompare;if(i<=o){var a=Math.floor((i+o)/2),f=n[a];return u(f,r)===t.Compare.LESS_THAN?e(n,r,a+1,o,u):u(f,r)===t.Compare.BIGGER_THAN?e(n,r,i,a-1,u):a}return t.DOES_NOT_EXIST}(e,r,0,o,i)}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(0)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.sequentialSearch=function(e,n){for(var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.defaultEquals,i=0;i2&&void 0!==arguments[2]?arguments[2]:t.defaultCompare,i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:t.defaultEquals,o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:t.defaultDiff,u=0,a=e.length-1,f=-1,l=-1;u<=a&&(0,t.biggerEquals)(n,e[u],r)&&(0,t.lesserEquals)(n,e[a],r);){if(l=o(n,e[u])/o(e[a],e[u]),f=u+Math.floor((a-u)*l),i(e[f],n))return f;r(e[f],n)===t.Compare.LESS_THAN?u=f+1:a=f-1}return t.DOES_NOT_EXIST}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(0),n(4)],void 0===(o="function"==typeof(r=function(e,t,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.binarySearch=function(e,r){for(var i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:t.defaultCompare,o=(0,n.quickSort)(e),u=0,a=o.length-1;u<=a;){var f=Math.floor((u+a)/2),l=o[f];if(i(l,r)===t.Compare.LESS_THAN)u=f+1;else{if(i(l,r)!==t.Compare.BIGGER_THAN)return f;a=f-1}}return t.DOES_NOT_EXIST}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(0)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.shellSort=function(e){for(var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare,r=e.length/2;r>0;){for(var i=r;i=r&&n(e[o-r],u)===t.Compare.BIGGER_THAN;)e[o]=e[o-r],o-=r;e[o]=u}r=2===r?1:Math.floor(5*r/11)}return e}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(0)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.selectionSort=void 0,e.selectionSort=function(e){for(var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare,r=e.length,i=void 0,o=0;o1&&void 0!==arguments[1]?arguments[1]:10;if(e.length<2)return e;for(var i=(0,t.findMinValue)(e),o=(0,t.findMaxValue)(e),u=1;(o-i)/u>=1;)e=r(e,n,u,i),u*=n;return e};var n=function(e,t,n,r){return Math.floor((e-t)/n%r)},r=function(e,t,r,i){for(var o=void 0,u=[],a=[],f=0;f=0;c--)o=n(e[c],i,r,t),a[--u[o]]=e[c];for(var h=0;h1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare;if(n.length>1){var i=n,o=i.length,u=Math.floor(o/2),a=e(n.slice(0,u),r),f=e(n.slice(u,o),r);n=function(e,n,r){for(var i=0,o=0,u=[];i0;)e[r++]=n,t--}),e}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(8)],void 0===(o="function"==typeof(r=function(e,t){"use strict";function n(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1&&void 0!==arguments[1]?arguments[1]:5;return e.length<2?e:function(e){for(var r=[],i=0;ir&&(r=e[i]);for(var o=Math.floor((r-n)/t)+1,u=[],a=0;a1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare,r=e.length,i=0;i1&&void 0!==arguments[1]?arguments[1]:t.defaultCompare,r=e.length,i=0;i0&&void 0!==arguments[0]&&arguments[0];!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.isDirected=t,this.vertices=[],this.adjList=new i.default}return o(e,[{key:"addVertex",value:function(e){this.vertices.includes(e)||(this.vertices.push(e),this.adjList.set(e,[]))}},{key:"addEdge",value:function(e,t){this.adjList.get(e)||this.addVertex(e),this.adjList.get(t)||this.addVertex(t),this.adjList.get(e).push(t),!0!==this.isDirected&&this.adjList.get(t).push(e)}},{key:"getVertices",value:function(){return this.vertices}},{key:"getAdjList",value:function(){return this.adjList}},{key:"toString",value:function(){for(var e="",t=0;t ";for(var n=this.adjList.get(this.vertices[t]),r=0;r0&&(u=a),f0&&(u=f),u!==t&&((0,n.swap)(e,t,u),r(e,u,i,o))}Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:n.defaultCompare,i=e.length;for(!function(e,t){for(var n=Math.floor(e.length/2);n>=0;n-=1)r(e,n,e.length,t)}(e,t);i>1;)(0,n.swap)(e,0,--i),r(e,0,i,t);return e},e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(0)],void 0===(o="function"==typeof(r=function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0}),e.MaxHeap=e.MinHeap=void 0;var r=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:t.defaultCompare;n(this,e),this.compareFn=r,this.heap=[]}return r(e,[{key:"getLeftIndex",value:function(e){return 2*e+1}},{key:"getRightIndex",value:function(e){return 2*e+2}},{key:"getParentIndex",value:function(e){if(0!==e)return Math.floor((e-1)/2)}},{key:"size",value:function(){return this.heap.length}},{key:"isEmpty",value:function(){return this.size()<=0}},{key:"clear",value:function(){this.heap=[]}},{key:"findMinimum",value:function(){return this.isEmpty()?void 0:this.heap[0]}},{key:"insert",value:function(e){if(null!=e){var t=this.heap.length;return this.heap.push(e),this.siftUp(t),!0}return!1}},{key:"siftDown",value:function(e){var n=e,r=this.getLeftIndex(e),i=this.getRightIndex(e),o=this.size();r0&&this.compareFn(this.heap[n],this.heap[e])===t.Compare.BIGGER_THAN;)(0,t.swap)(this.heap,n,e),e=n,n=this.getParentIndex(e)}},{key:"extract",value:function(){if(!this.isEmpty()){if(1===this.size())return this.heap.shift();var e=this.heap[0];return this.heap[0]=this.heap.pop(),this.siftDown(0),e}}},{key:"heapify",value:function(e){e&&(this.heap=e);for(var t=Math.floor(this.size()/2)-1,n=0;n<=t;n++)this.siftDown(n);return this.heap}},{key:"getAsArray",value:function(){return this.heap}}]),e}();e.MaxHeap=function(e){function r(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:t.defaultCompare;n(this,r);var i=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,e));return i.compareFn=e,i.compareFn=(0,t.reverseCompare)(e),i}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(r,e),r}(i)})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t,n(0),n(10),n(9)],void 0===(o="function"==typeof(r=function(e,t,n,r,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,u=(o=r)&&o.__esModule?o:{default:o},a=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultCompare;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var r=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return r.compareFn=e,r.root=null,r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),a(t,[{key:"getNodeHeight",value:function(e){return null==e?-1:Math.max(this.getNodeHeight(e.left),this.getNodeHeight(e.right))+1}},{key:"rotationLL",value:function(e){var t=e.left;return e.left=t.right,t.right=e,t}},{key:"rotationRR",value:function(e){var t=e.right;return e.right=t.left,t.left=e,t}},{key:"rotationLR",value:function(e){return e.left=this.rotationRR(e.left),this.rotationLL(e)}},{key:"rotationRL",value:function(e){return e.right=this.rotationLL(e.right),this.rotationRR(e)}},{key:"getBalanceFactor",value:function(e){var t=this.getNodeHeight(e.left)-this.getNodeHeight(e.right);switch(t){case-2:return f.UNBALANCED_RIGHT;case-1:return f.SLIGHTLY_UNBALANCED_RIGHT;case 1:return f.SLIGHTLY_UNBALANCED_LEFT;case 2:return f.UNBALANCED_LEFT;default:return f.BALANCED}}},{key:"insert",value:function(e){this.root=this.insertNode(this.root,e)}},{key:"insertNode",value:function(e,t){if(null==e)return new i.Node(t);if(this.compareFn(t,e.key)===n.Compare.LESS_THAN)e.left=this.insertNode(e.left,t);else{if(this.compareFn(t,e.key)!==n.Compare.BIGGER_THAN)return e;e.right=this.insertNode(e.right,t)}var r=this.getBalanceFactor(e);if(r===f.UNBALANCED_LEFT){if(this.compareFn(t,e.left.key)!==n.Compare.LESS_THAN)return this.rotationLR(e);e=this.rotationLL(e)}if(r===f.UNBALANCED_RIGHT){if(this.compareFn(t,e.right.key)!==n.Compare.BIGGER_THAN)return this.rotationRL(e);e=this.rotationRR(e)}return e}},{key:"removeNode",value:function(e,n){if(null==(e=function e(t,n,r){null===t&&(t=Function.prototype);var i=Object.getOwnPropertyDescriptor(t,n);if(void 0===i){var o=Object.getPrototypeOf(t);return null===o?void 0:e(o,n,r)}if("value"in i)return i.value;var u=i.get;return void 0!==u?u.call(r):void 0}(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"removeNode",this).call(this,e,n)))return e;var r=this.getBalanceFactor(e);if(r===f.UNBALANCED_LEFT){if(this.getBalanceFactor(e.left)===f.BALANCED||this.getBalanceFactor(e.left)===f.SLIGHTLY_UNBALANCED_LEFT)return this.rotationLL(e);if(this.getBalanceFactor(e.left)===f.SLIGHTLY_UNBALANCED_RIGHT)return this.rotationLR(e.left)}if(r===f.UNBALANCED_RIGHT){if(this.getBalanceFactor(e.right)===f.BALANCED||this.getBalanceFactor(e.right)===f.SLIGHTLY_UNBALANCED_RIGHT)return this.rotationRR(e);if(this.getBalanceFactor(e.right)===f.SLIGHTLY_UNBALANCED_LEFT)return this.rotationRL(e.right)}return e}}]),t}(u.default);t.default=l,e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.fibonacci=function e(t){return t<1?0:t<=2?1:e(t-1)+e(t-2)},e.fibonacciIterative=function(e){if(e<1)return 0;for(var t=0,n=1,r=e,i=2;i<=e;i++)r=n+t,t=n,n=r;return r},e.fibonacciMemoization=function(e){if(e<1)return 0;var t=[0,1];return function e(n){return null!=t[n]?t[n]:t[n]=e(n-1)+e(n-2)}(e)}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t],void 0===(o="function"==typeof(r=function(e){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.factorialIterative=function(e){if(!(e<0)){for(var t=1,n=e;n>1;n--)t*=n;return t}},e.factorial=function e(t){if(!(t<0))return 1===t||0===t?1:t*e(t-1)}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(1)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.ValuePairLazy=void 0,e.ValuePairLazy=function(e){function t(e,n){var r=arguments.length>2&&void 0!==arguments[2]&&arguments[2];!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var i=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,n));return i.key=e,i.value=n,i.isDeleted=r,i}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),t}(t.ValuePair)})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t,n(0),n(51)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultToString;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.toStrFn=t,this.table={}}return i(e,[{key:"loseloseHashCode",value:function(e){if("number"==typeof e)return e;for(var t=this.toStrFn(e),n=0,r=0;r "+this.table[e[0]].toString()+"}",n=1;n "+this.table[e[n]].toString()+"}";return t}}]),e}();t.default=o,e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t,n(0),n(1)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultToString;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.toStrFn=t,this.table={}}return i(e,[{key:"loseloseHashCode",value:function(e){if("number"==typeof e)return e;for(var t=this.toStrFn(e),n=0,r=0;r "+this.table[e[0]].toString()+"}",n=1;n "+this.table[e[n]].toString()+"}";return t}}]),e}();t.default=o,e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t,n(0),n(2),n(1)],void 0===(o="function"==typeof(r=function(e,t,n,r,i){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var o,u=(o=r)&&o.__esModule?o:{default:o},a=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultToString;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.toStrFn=t,this.table={}}return a(e,[{key:"loseloseHashCode",value:function(e){if("number"==typeof e)return e;for(var t=this.toStrFn(e),n=0,r=0;r "+this.table[e[0]].toString()+"}",n=1;n "+this.table[e[n]].toString()+"}";return t}}]),e}();t.default=f,e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t,n(0),n(1)],void 0===(o="function"==typeof(r=function(e,t,n,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:n.defaultToString;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.toStrFn=t,this.table={}}return i(e,[{key:"loseloseHashCode",value:function(e){if("number"==typeof e)return e;for(var t=this.toStrFn(e),n=0,r=0;r "+this.table[e[0]].toString()+"}",n=1;n "+this.table[e[n]].toString()+"}";return t}}]),e}();t.default=o,e.exports=t.default})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e,t){for(var n=0;n0&&(o=i,u=r),u.forEach(function(e){o.includes(e)&&n.add(e)}),n}},{key:"difference",value:function(t){var n=new e;return this.values().forEach(function(e){t.has(e)||n.add(e)}),n}},{key:"isSubsetOf",value:function(e){if(this.size()>e.size())return!1;var t=!0;return this.values().every(function(n){return!!e.has(n)||(t=!1,!1)}),t}},{key:"isEmpty",value:function(){return 0===this.size()}},{key:"size",value:function(){return Object.keys(this.items).length}},{key:"clear",value:function(){this.items={}}},{key:"toString",value:function(){if(this.isEmpty())return"";for(var e=this.values(),t=""+e[0],n=1;n0&&void 0!==arguments[0]?arguments[0]:n.defaultEquals,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:n.defaultCompare;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t);var i=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e));return i.equalsFn=e,i.compareFn=r,i}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),u(t,[{key:"push",value:function(e){if(this.isEmpty())a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"push",this).call(this,e);else{var n=this.getIndexNextSortedElement(e);a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"insert",this).call(this,e,n)}}},{key:"insert",value:function(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0;if(this.isEmpty())return a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"insert",this).call(this,e,0===n?n:0);var r=this.getIndexNextSortedElement(e);return a(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"insert",this).call(this,e,r)}},{key:"getIndexNextSortedElement",value:function(e){for(var t=this.head,r=0;r0&&void 0!==arguments[0]?arguments[0]:n.defaultEquals;return function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e))}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}(t,e),a(t,[{key:"push",value:function(e){var t=new i.Node(e);null==this.head?this.head=t:this.getElementAt(this.size()-1).next=t,t.next=this.head,this.count++}},{key:"insert",value:function(e,t){if(t>=0&&t<=this.count){var n=new i.Node(e),r=this.head;if(0===t)null==this.head?(this.head=n,n.next=this.head):(n.next=r,r=this.getElementAt(this.size()),this.head=n,r.next=this.head);else{var o=this.getElementAt(t-1);n.next=o.next,o.next=n}return this.count++,!0}return!1}},{key:"removeAt",value:function(e){if(e>=0&&e1;)if(i=t.removeFront(),o=t.removeBack(),i!==o)return!1;return!0};var n,r=(n=t)&&n.__esModule?n:{default:n}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(7)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.hotPotato=function(e,t){for(var n=new r.default,i=[],o=0;o1;){for(var u=0;u=0?t.push(o):t.isEmpty()?n=!1:(u=t.pop(),"([{".indexOf(u)!==")]}".indexOf(o)&&(n=!1)),i++;return n&&t.isEmpty()};var n,r=(n=t)&&n.__esModule?n:{default:n}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(3)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.decimalToBinary=function(e){for(var t=new r.default,n=e,i=void 0,o="";n>0;)i=Math.floor(n%2),t.push(i),n=Math.floor(n/2);for(;!t.isEmpty();)o+=t.pop().toString();return o},e.baseConverter=function(e,t){var n=new r.default,i=e,o=void 0,u="";if(!(t>=2&&t<=36))return"";for(;i>0;)o=Math.floor(i%t),n.push(o),i=Math.floor(i/t);for(;!n.isEmpty();)u+="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n.pop()];return u};var n,r=(n=t)&&n.__esModule?n:{default:n}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[t,n(3)],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.hanoiStack=function(e){for(var t=new r.default,n=new r.default,i=new r.default,o=e;o>0;o--)t.push(o);return function e(t,n,r,i,o,u,a){var f=arguments.length>7&&void 0!==arguments[7]?arguments[7]:[];if(t<=0)return f;if(1===t){i.push(n.pop());var l={};l[o]=n.toString(),l[u]=r.toString(),l[a]=i.toString(),f.push(l)}else{e(t-1,n,i,r,o,a,u,f),i.push(n.pop());var s={};s[o]=n.toString(),s[u]=r.toString(),s[a]=i.toString(),f.push(s),e(t-1,r,n,i,u,o,a,f)}return f}(e,t,i,n,"source","helper","dest")},e.hanoi=function e(t,n,r,i){var o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:[];return t<=0?o:(1===t?o.push([n,i]):(e(t-1,n,i,r,o),o.push([n,i]),e(t-1,r,n,i,o)),o)};var n,r=(n=t)&&n.__esModule?n:{default:n}})?r.apply(t,i):r)||(e.exports=o)},function(e,t,n){var r,i,o;i=[e,t],void 0===(o="function"==typeof(r=function(e,t){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e,t){for(var n=0;n compareFn(b, a);\n}\n\nexport function defaultDiff(a, b) {\n return Number(a) - Number(b);\n}\n","export class ValuePair {\n constructor(key, value) {\n this.key = key;\n this.value = value;\n }\n toString() {\n return `[#${this.key}: ${this.value}]`;\n }\n}\n","import { defaultEquals } from '../util';\nimport { Node } from './models/linked-list-models';\n\nexport default class LinkedList {\n constructor(equalsFn = defaultEquals) {\n this.equalsFn = equalsFn;\n this.count = 0;\n this.head = undefined;\n }\n push(element) {\n const node = new Node(element);\n let current;\n if (this.head == null) {\n // catches null && undefined\n this.head = node;\n } else {\n current = this.head;\n while (current.next != null) {\n current = current.next;\n }\n current.next = node;\n }\n this.count++;\n }\n getElementAt(index) {\n if (index >= 0 && index <= this.count) {\n let node = this.head;\n for (let i = 0; i < index && node != null; i++) {\n node = node.next;\n }\n return node;\n }\n return undefined;\n }\n insert(element, index) {\n if (index >= 0 && index <= this.count) {\n const node = new Node(element);\n if (index === 0) {\n const current = this.head;\n node.next = current;\n this.head = node;\n } else {\n const previous = this.getElementAt(index - 1);\n node.next = previous.next;\n previous.next = node;\n }\n this.count++;\n return true;\n }\n return false;\n }\n removeAt(index) {\n if (index >= 0 && index < this.count) {\n let current = this.head;\n if (index === 0) {\n this.head = current.next;\n } else {\n const previous = this.getElementAt(index - 1);\n current = previous.next;\n previous.next = current.next;\n }\n this.count--;\n return current.element;\n }\n return undefined;\n }\n remove(element) {\n const index = this.indexOf(element);\n return this.removeAt(index);\n }\n indexOf(element) {\n let current = this.head;\n for (let i = 0; i < this.size() && current != null; i++) {\n if (this.equalsFn(element, current.element)) {\n return i;\n }\n current = current.next;\n }\n return -1;\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n return this.count;\n }\n getHead() {\n return this.head;\n }\n clear() {\n this.head = undefined;\n this.count = 0;\n }\n toString() {\n if (this.head == null) {\n return '';\n }\n let objString = `${this.head.element}`;\n let current = this.head.next;\n for (let i = 1; i < this.size() && current != null; i++) {\n objString = `${objString},${current.element}`;\n current = current.next;\n }\n return objString;\n }\n}\n","// @ts-check\n\nexport default class Stack {\n constructor() {\n this.count = 0;\n this.items = {};\n }\n push(element) {\n this.items[this.count] = element;\n this.count++;\n }\n pop() {\n if (this.isEmpty()) {\n return undefined;\n }\n this.count--;\n const result = this.items[this.count];\n delete this.items[this.count];\n return result;\n }\n peek() {\n if (this.isEmpty()) {\n return undefined;\n }\n return this.items[this.count - 1];\n }\n isEmpty() {\n return this.count === 0;\n }\n size() {\n return this.count;\n }\n clear() {\n /* while (!this.isEmpty()) {\n this.pop();\n } */\n this.items = {};\n this.count = 0;\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n let objString = `${this.items[0]}`;\n for (let i = 1; i < this.count; i++) {\n objString = `${objString},${this.items[i]}`;\n }\n return objString;\n }\n}\n","import { Compare, defaultCompare, swap } from '../../util';\n\nfunction partition(array, left, right, compareFn) {\n const pivot = array[Math.floor((right + left) / 2)];\n let i = left;\n let j = right;\n\n while (i <= j) {\n while (compareFn(array[i], pivot) === Compare.LESS_THAN) {\n i++;\n }\n while (compareFn(array[j], pivot) === Compare.BIGGER_THAN) {\n j--;\n }\n if (i <= j) {\n swap(array, i, j);\n i++;\n j--;\n }\n }\n return i;\n}\nfunction quick(array, left, right, compareFn) {\n let index;\n if (array.length > 1) {\n index = partition(array, left, right, compareFn);\n if (left < index - 1) {\n quick(array, left, index - 1, compareFn);\n }\n if (index < right) {\n quick(array, index, right, compareFn);\n }\n }\n return array;\n}\nexport function quickSort(array, compareFn = defaultCompare) {\n return quick(array, 0, array.length - 1, compareFn);\n}\n","import { defaultCompare, Compare } from '../../util';\n\nexport function findMaxValue(array, compareFn = defaultCompare) {\n if (array && array.length > 0) {\n let max = array[0];\n for (let i = 1; i < array.length; i++) {\n if (compareFn(max, array[i]) === Compare.LESS_THAN) {\n max = array[i];\n }\n }\n return max;\n }\n return undefined;\n}\nexport function findMinValue(array, compareFn = defaultCompare) {\n if (array && array.length > 0) {\n let min = array[0];\n for (let i = 1; i < array.length; i++) {\n if (compareFn(min, array[i]) === Compare.BIGGER_THAN) {\n min = array[i];\n }\n }\n return min;\n }\n return undefined;\n}\n","export class Node {\n constructor(element, next) {\n this.element = element;\n this.next = next;\n }\n}\nexport class DoublyNode extends Node {\n constructor(element, next, prev) {\n super(element, next);\n this.prev = prev;\n }\n}\n","// @ts-check\n\nexport default class Queue {\n constructor() {\n this.count = 0;\n this.lowestCount = 0;\n this.items = {};\n }\n\n enqueue(element) {\n this.items[this.count] = element;\n this.count++;\n }\n\n dequeue() {\n if (this.isEmpty()) {\n return undefined;\n }\n const result = this.items[this.lowestCount];\n delete this.items[this.lowestCount];\n this.lowestCount++;\n return result;\n }\n\n peek() {\n if (this.isEmpty()) {\n return undefined;\n }\n return this.items[this.lowestCount];\n }\n\n isEmpty() {\n return this.size() === 0;\n }\n\n clear() {\n this.items = {};\n this.count = 0;\n this.lowestCount = 0;\n }\n\n size() {\n return this.count - this.lowestCount;\n }\n\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n let objString = `${this.items[this.lowestCount]}`;\n for (let i = this.lowestCount + 1; i < this.count; i++) {\n objString = `${objString},${this.items[i]}`;\n }\n return objString;\n }\n}\n","import { Compare, defaultCompare } from '../../util';\n\nexport const insertionSort = (array, compareFn = defaultCompare) => {\n const { length } = array;\n let temp;\n for (let i = 1; i < length; i++) {\n let j = i;\n temp = array[i];\n // console.log('to be inserted ' + temp);\n while (j > 0 && compareFn(array[j - 1], temp) === Compare.BIGGER_THAN) {\n // console.log('shift ' + array[j - 1]);\n array[j] = array[j - 1];\n j--;\n }\n // console.log('insert ' + temp);\n array[j] = temp;\n }\n return array;\n};\n","export class Node {\n constructor(key) {\n this.key = key;\n this.left = undefined;\n this.right = undefined;\n }\n toString() {\n return `${this.key}`;\n }\n}\n","import { Compare, defaultCompare } from '../util';\nimport { Node } from './models/node';\n\nexport default class BinarySearchTree {\n constructor(compareFn = defaultCompare) {\n this.compareFn = compareFn;\n this.root = undefined;\n }\n insert(key) {\n // special case: first key\n if (this.root == null) {\n this.root = new Node(key);\n } else {\n this.insertNode(this.root, key);\n }\n }\n insertNode(node, key) {\n if (this.compareFn(key, node.key) === Compare.LESS_THAN) {\n if (node.left == null) {\n node.left = new Node(key);\n } else {\n this.insertNode(node.left, key);\n }\n } else if (node.right == null) {\n node.right = new Node(key);\n } else {\n this.insertNode(node.right, key);\n }\n }\n getRoot() {\n return this.root;\n }\n search(key) {\n return this.searchNode(this.root, key);\n }\n searchNode(node, key) {\n if (node == null) {\n return false;\n }\n if (this.compareFn(key, node.key) === Compare.LESS_THAN) {\n return this.searchNode(node.left, key);\n } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {\n return this.searchNode(node.right, key);\n }\n return true;\n }\n inOrderTraverse(callback) {\n this.inOrderTraverseNode(this.root, callback);\n }\n inOrderTraverseNode(node, callback) {\n if (node != null) {\n this.inOrderTraverseNode(node.left, callback);\n callback(node.key);\n this.inOrderTraverseNode(node.right, callback);\n }\n }\n preOrderTraverse(callback) {\n this.preOrderTraverseNode(this.root, callback);\n }\n preOrderTraverseNode(node, callback) {\n if (node != null) {\n callback(node.key);\n this.preOrderTraverseNode(node.left, callback);\n this.preOrderTraverseNode(node.right, callback);\n }\n }\n postOrderTraverse(callback) {\n this.postOrderTraverseNode(this.root, callback);\n }\n postOrderTraverseNode(node, callback) {\n if (node != null) {\n this.postOrderTraverseNode(node.left, callback);\n this.postOrderTraverseNode(node.right, callback);\n callback(node.key);\n }\n }\n min() {\n return this.minNode(this.root);\n }\n minNode(node) {\n let current = node;\n while (current != null && current.left != null) {\n current = current.left;\n }\n return current;\n }\n max() {\n return this.maxNode(this.root);\n }\n maxNode(node) {\n let current = node;\n while (current != null && current.right != null) {\n current = current.right;\n }\n return current;\n }\n remove(key) {\n this.root = this.removeNode(this.root, key);\n }\n removeNode(node, key) {\n if (node == null) {\n return undefined;\n }\n if (this.compareFn(key, node.key) === Compare.LESS_THAN) {\n node.left = this.removeNode(node.left, key);\n return node;\n } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {\n node.right = this.removeNode(node.right, key);\n return node;\n }\n // key is equal to node.item\n // handle 3 special conditions\n // 1 - a leaf node\n // 2 - a node with only 1 child\n // 3 - a node with 2 children\n // case 1\n if (node.left == null && node.right == null) {\n node = undefined;\n return node;\n }\n // case 2\n if (node.left == null) {\n node = node.right;\n return node;\n } else if (node.right == null) {\n node = node.left;\n return node;\n }\n // case 3\n const aux = this.minNode(node.right);\n node.key = aux.key;\n node.right = this.removeNode(node.right, aux.key);\n return node;\n }\n}\n","import { defaultToString } from '../util';\nimport { ValuePair } from './models/value-pair';\n\nexport default class Dictionary {\n constructor(toStrFn = defaultToString) {\n this.toStrFn = toStrFn;\n this.table = {};\n }\n set(key, value) {\n if (key != null && value != null) {\n const tableKey = this.toStrFn(key);\n this.table[tableKey] = new ValuePair(key, value);\n return true;\n }\n return false;\n }\n get(key) {\n const valuePair = this.table[this.toStrFn(key)];\n return valuePair == null ? undefined : valuePair.value;\n }\n hasKey(key) {\n return this.table[this.toStrFn(key)] != null;\n }\n remove(key) {\n if (this.hasKey(key)) {\n delete this.table[this.toStrFn(key)];\n return true;\n }\n return false;\n }\n values() {\n return this.keyValues().map(valuePair => valuePair.value);\n }\n keys() {\n return this.keyValues().map(valuePair => valuePair.key);\n }\n keyValues() {\n return Object.values(this.table);\n }\n forEach(callbackFn) {\n const valuePairs = this.keyValues();\n for (let i = 0; i < valuePairs.length; i++) {\n const result = callbackFn(valuePairs[i].key, valuePairs[i].value);\n if (result === false) {\n break;\n }\n }\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n return Object.keys(this.table).length;\n }\n clear() {\n this.table = {};\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n const valuePairs = this.keyValues();\n let objString = `${valuePairs[0].toString()}`;\n for (let i = 1; i < valuePairs.length; i++) {\n objString = `${objString},${valuePairs[i].toString()}`;\n }\n return objString;\n }\n}\n","import { defaultEquals } from '../util';\nimport LinkedList from './linked-list';\nimport { DoublyNode } from './models/linked-list-models';\n\nexport default class DoublyLinkedList extends LinkedList {\n constructor(equalsFn = defaultEquals) {\n super(equalsFn);\n this.tail = undefined;\n }\n push(element) {\n const node = new DoublyNode(element);\n if (this.head == null) {\n this.head = node;\n this.tail = node; // NEW\n } else {\n // attach to the tail node // NEW\n this.tail.next = node;\n node.prev = this.tail;\n this.tail = node;\n }\n this.count++;\n }\n insert(element, index) {\n if (index >= 0 && index <= this.count) {\n const node = new DoublyNode(element);\n let current = this.head;\n if (index === 0) {\n if (this.head == null) { // NEW\n this.head = node;\n this.tail = node; // NEW\n } else {\n node.next = this.head;\n this.head.prev = node; // NEW\n this.head = node;\n }\n } else if (index === this.count) { // last item NEW\n current = this.tail;\n current.next = node;\n node.prev = current;\n this.tail = node;\n } else {\n const previous = this.getElementAt(index - 1);\n current = previous.next;\n node.next = current;\n previous.next = node;\n current.prev = node; // NEW\n node.prev = previous; // NEW\n }\n this.count++;\n return true;\n }\n return false;\n }\n removeAt(index) {\n if (index >= 0 && index < this.count) {\n let current = this.head;\n if (index === 0) {\n this.head = this.head.next;\n // if there is only one item, then we update tail as well //NEW\n if (this.count === 1) {\n // {2}\n this.tail = undefined;\n } else {\n this.head.prev = undefined;\n }\n } else if (index === this.count - 1) {\n // last item //NEW\n current = this.tail;\n this.tail = current.prev;\n this.tail.next = undefined;\n } else {\n current = this.getElementAt(index);\n const previous = current.prev;\n // link previous with current's next - skip it to remove\n previous.next = current.next;\n current.next.prev = previous; // NEW\n }\n this.count--;\n return current.element;\n }\n return undefined;\n }\n indexOf(element) {\n let current = this.head;\n let index = 0;\n while (current != null) {\n if (this.equalsFn(element, current.element)) {\n return index;\n }\n index++;\n current = current.next;\n }\n return -1;\n }\n getHead() {\n return this.head;\n }\n getTail() {\n return this.tail;\n }\n clear() {\n super.clear();\n this.tail = undefined;\n }\n toString() {\n if (this.head == null) {\n return '';\n }\n let objString = `${this.head.element}`;\n let current = this.head.next;\n while (current != null) {\n objString = `${objString},${current.element}`;\n current = current.next;\n }\n return objString;\n }\n inverseToString() {\n if (this.tail == null) {\n return '';\n }\n let objString = `${this.tail.element}`;\n let previous = this.tail.prev;\n while (previous != null) {\n objString = `${objString},${previous.element}`;\n previous = previous.prev;\n }\n return objString;\n }\n}\n","// @ts-check\n\nexport default class Deque {\n constructor() {\n this.count = 0;\n this.lowestCount = 0;\n this.items = {};\n }\n\n addFront(element) {\n if (this.isEmpty()) {\n this.addBack(element);\n } else if (this.lowestCount > 0) {\n this.lowestCount--;\n this.items[this.lowestCount] = element;\n } else {\n for (let i = this.count; i > 0; i--) {\n this.items[i] = this.items[i - 1];\n }\n this.count++;\n this.items[0] = element;\n }\n }\n\n addBack(element) {\n this.items[this.count] = element;\n this.count++;\n }\n\n removeFront() {\n if (this.isEmpty()) {\n return undefined;\n }\n const result = this.items[this.lowestCount];\n delete this.items[this.lowestCount];\n this.lowestCount++;\n return result;\n }\n\n removeBack() {\n if (this.isEmpty()) {\n return undefined;\n }\n this.count--;\n const result = this.items[this.count];\n delete this.items[this.count];\n return result;\n }\n\n peekFront() {\n if (this.isEmpty()) {\n return undefined;\n }\n return this.items[this.lowestCount];\n }\n\n peekBack() {\n if (this.isEmpty()) {\n return undefined;\n }\n return this.items[this.count - 1];\n }\n\n isEmpty() {\n return this.size() === 0;\n }\n\n clear() {\n this.items = {};\n this.count = 0;\n this.lowestCount = 0;\n }\n\n size() {\n return this.count - this.lowestCount;\n }\n\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n let objString = `${this.items[this.lowestCount]}`;\n for (let i = this.lowestCount + 1; i < this.count; i++) {\n objString = `${objString},${this.items[i]}`;\n }\n return objString;\n }\n}\n","export const floydWarshall = graph => {\n const dist = [];\n const { length } = graph;\n for (let i = 0; i < length; i++) {\n dist[i] = [];\n for (let j = 0; j < length; j++) {\n if (i === j) {\n dist[i][j] = 0;\n } else if (!isFinite(graph[i][j])) {\n dist[i][j] = Infinity;\n } else {\n dist[i][j] = graph[i][j];\n }\n }\n }\n for (let k = 0; k < length; k++) {\n for (let i = 0; i < length; i++) {\n for (let j = 0; j < length; j++) {\n if (dist[i][k] + dist[k][j] < dist[i][j]) {\n dist[i][j] = dist[i][k] + dist[k][j];\n }\n }\n }\n }\n return dist;\n};\n","const UNASSIGNED = 0;\n\nfunction usedInRow(matrix, row, num) {\n for (let col = 0; col < matrix.length; col++) {\n if (matrix[row][col] === num) {\n return true;\n }\n }\n return false;\n}\n\nfunction usedInCol(matrix, col, num) {\n for (let row = 0; row < matrix.length; row++) {\n if (matrix[row][col] === num) {\n return true;\n }\n }\n return false;\n}\n\nfunction usedInBox(matrix, boxStartRow, boxStartCol, num) {\n for (let row = 0; row < 3; row++) {\n for (let col = 0; col < 3; col++) {\n if (matrix[row + boxStartRow][col + boxStartCol] === num) {\n return true;\n }\n }\n }\n return false;\n}\n\nfunction isSafe(matrix, row, col, num) {\n return (\n !usedInRow(matrix, row, num) &&\n !usedInCol(matrix, col, num) &&\n !usedInBox(matrix, row - (row % 3), col - (col % 3), num)\n );\n}\nfunction solveSudoku(matrix) {\n let row = 0;\n let col = 0;\n let checkBlankSpaces = false;\n\n for (row = 0; row < matrix.length; row++) {\n for (col = 0; col < matrix[row].length; col++) {\n if (matrix[row][col] === UNASSIGNED) {\n checkBlankSpaces = true;\n break;\n }\n }\n if (checkBlankSpaces === true) {\n break;\n }\n }\n if (checkBlankSpaces === false) {\n return true;\n }\n\n for (let num = 1; num <= 9; num++) {\n if (isSafe(matrix, row, col, num)) {\n matrix[row][col] = num;\n if (solveSudoku(matrix)) {\n return true;\n }\n matrix[row][col] = UNASSIGNED;\n }\n }\n return false;\n}\n\nexport function sudokuSolver(matrix) {\n if (solveSudoku(matrix) === true) {\n return matrix;\n }\n return 'NO SOLUTION EXISTS!';\n}\n","function isSafe(maze, x, y) {\n const n = maze.length;\n if (x >= 0 && y >= 0 && x < n && y < n && maze[x][y] !== 0) {\n return true;\n }\n return false;\n}\n\nfunction findPath(maze, x, y, solution) {\n const n = maze.length;\n if (x === n - 1 && y === n - 1) {\n solution[x][y] = 1;\n return true;\n }\n if (isSafe(maze, x, y) === true) {\n solution[x][y] = 1;\n if (findPath(maze, x + 1, y, solution)) {\n return true;\n }\n if (findPath(maze, x, y + 1, solution)) {\n return true;\n }\n solution[x][y] = 0;\n return false;\n }\n return false;\n}\n\nexport function ratInAMaze(maze) {\n const solution = [];\n for (let i = 0; i < maze.length; i++) {\n solution[i] = [];\n for (let j = 0; j < maze[i].length; j++) {\n solution[i][j] = 0;\n }\n }\n if (findPath(maze, 0, 0, solution) === true) {\n return solution;\n }\n return 'NO PATH FOUND';\n}\n","export function matrixChainOrder(p, i = 1, j = p.length - 1) {\n if (i === j) {\n return 0;\n }\n let min = Number.MAX_SAFE_INTEGER;\n for (let k = i; k < j; k++) {\n const count =\n matrixChainOrder(p, i, k) + matrixChainOrder(p, k + 1, j) + ((p[i - 1] * p[k]) * p[j]);\n if (count < min) {\n min = count;\n }\n }\n return min;\n}\n","function printOptimalParenthesis(s, i, j) {\n if (i === j) {\n // console.log('A[' + i + ']');\n } else {\n // console.log('(');\n printOptimalParenthesis(s, i, s[i][j]);\n printOptimalParenthesis(s, s[i][j] + 1, j);\n // console.log(')');\n }\n}\n\nexport function matrixChainOrder(p) {\n const n = p.length;\n const m = [];\n const s = [];\n for (let i = 1; i <= n; i++) {\n m[i] = [];\n m[i][i] = 0;\n }\n for (let i = 0; i <= n; i++) {\n // to help printing the optimal solution\n s[i] = []; // auxiliary\n for (let j = 0; j <= n; j++) {\n s[i][j] = 0;\n }\n }\n for (let l = 2; l < n; l++) {\n for (let i = 1; i <= (n - l) + 1; i++) {\n const j = (i + l) - 1;\n m[i][j] = Number.MAX_SAFE_INTEGER;\n for (let k = i; k <= j - 1; k++) {\n // q = cost/scalar multiplications\n const q = m[i][k] + m[k + 1][j] + ((p[i - 1] * p[k]) * p[j]);\n if (q < m[i][j]) {\n m[i][j] = q;\n s[i][j] = k; // s[i,j] = Second auxiliary table that stores k\n }\n }\n }\n }\n // console.log(m);\n // console.log(s);\n printOptimalParenthesis(s, 1, n - 1);\n return m[1][n - 1];\n}\n\n","export function lcs(wordX, wordY, m = wordX.length, n = wordY.length) {\n if (m === 0 || n === 0) {\n return 0;\n }\n if (wordX[m - 1] === wordY[n - 1]) {\n return 1 + lcs(wordX, wordY, m - 1, n - 1);\n }\n const a = lcs(wordX, wordY, m, n - 1);\n const b = lcs(wordX, wordY, m - 1, n);\n return a > b ? a : b;\n}\n","function printSolution(solution, wordX, m, n) {\n let a = m;\n let b = n;\n let x = solution[a][b];\n let answer = '';\n while (x !== '0') {\n if (solution[a][b] === 'diagonal') {\n answer = wordX[a - 1] + answer;\n a--;\n b--;\n } else if (solution[a][b] === 'left') {\n b--;\n } else if (solution[a][b] === 'top') {\n a--;\n }\n x = solution[a][b];\n }\n return answer;\n}\nexport function lcs(wordX, wordY) {\n const m = wordX.length;\n const n = wordY.length;\n const l = [];\n const solution = [];\n for (let i = 0; i <= m; i++) {\n l[i] = [];\n solution[i] = [];\n for (let j = 0; j <= n; j++) {\n l[i][j] = 0;\n solution[i][j] = '0';\n }\n }\n for (let i = 0; i <= m; i++) {\n for (let j = 0; j <= n; j++) {\n if (i === 0 || j === 0) {\n l[i][j] = 0;\n } else if (wordX[i - 1] === wordY[j - 1]) {\n l[i][j] = l[i - 1][j - 1] + 1;\n solution[i][j] = 'diagonal';\n } else {\n const a = l[i - 1][j];\n const b = l[i][j - 1];\n l[i][j] = a > b ? a : b; // max(a,b)\n solution[i][j] = l[i][j] === l[i - 1][j] ? 'top' : 'left';\n }\n }\n // console.log(l[i].join());\n // console.log(solution[i].join());\n }\n return printSolution(solution, wordX, m, n);\n}\n","export function lcs(wordX, wordY) {\n const m = wordX.length;\n const n = wordY.length;\n const l = [];\n for (let i = 0; i <= m; i++) {\n l[i] = [];\n for (let j = 0; j <= n; j++) {\n l[i][j] = 0;\n }\n }\n for (let i = 0; i <= m; i++) {\n for (let j = 0; j <= n; j++) {\n if (i === 0 || j === 0) {\n l[i][j] = 0;\n } else if (wordX[i - 1] === wordY[j - 1]) {\n l[i][j] = l[i - 1][j - 1] + 1;\n } else {\n const a = l[i - 1][j];\n const b = l[i][j - 1];\n l[i][j] = a > b ? a : b; // max(a,b)\n }\n }\n // console.log(l[i].join());\n }\n return l[m][n];\n}\n","export function knapSack(capacity, weights, values) {\n const n = values.length;\n let load = 0;\n let val = 0;\n for (let i = 0; i < n && load < capacity; i++) {\n if (weights[i] <= capacity - load) {\n val += values[i];\n load += weights[i];\n // console.log('using item ' + (i + 1) + ' for the solution');\n } else {\n const r = (capacity - load) / weights[i];\n val += r * values[i];\n load += weights[i];\n // console.log('using ratio of ' + r + ' for item ' + (i + 1) + ' for the solution');\n }\n }\n return val;\n}\n","export function knapSack(capacity, weights, values, n) {\n if (n === 0 || capacity === 0) {\n return 0;\n }\n if (weights[n - 1] > capacity) {\n return knapSack(capacity, weights, values, n - 1);\n }\n const a = values[n - 1] + knapSack(capacity - weights[n - 1], weights, values, n - 1);\n const b = knapSack(capacity, weights, values, n - 1);\n return a > b ? a : b;\n}\n","function findValues(n, capacity, kS) {\n let i = n;\n let k = capacity;\n // console.log('Items that are part of the solution:');\n while (i > 0 && k > 0) {\n if (kS[i][k] !== kS[i - 1][k]) {\n // console.log(\n // item ' + i + ' can be part of solution w,v: ' + weights[i - 1] + ',' + values[i - 1]\n // );\n i--;\n k -= kS[i][k];\n } else {\n i--;\n }\n }\n}\n\nexport function knapSack(capacity, weights, values, n) {\n const kS = [];\n for (let i = 0; i <= n; i++) {\n kS[i] = [];\n }\n for (let i = 0; i <= n; i++) {\n for (let w = 0; w <= capacity; w++) {\n if (i === 0 || w === 0) {\n kS[i][w] = 0;\n } else if (weights[i - 1] <= w) {\n const a = values[i - 1] + kS[i - 1][w - weights[i - 1]];\n const b = kS[i - 1][w];\n kS[i][w] = a > b ? a : b; // max(a,b)\n // console.log(a + ' can be part of the solution');\n } else {\n kS[i][w] = kS[i - 1][w];\n }\n }\n // console.log(kS[i].join());\n }\n // extra algorithm to find the items that are part of the solution\n findValues(n, capacity, kS);\n return kS[n][capacity];\n}\n","export function minCoinChange(coins, amount) {\n const change = [];\n let total = 0;\n for (let i = coins.length; i >= 0; i--) {\n const coin = coins[i];\n while (total + coin <= amount) {\n change.push(coin);\n total += coin;\n }\n }\n return change;\n}\n","export function minCoinChange(coins, amount) {\n const cache = [];\n\n const makeChange = (value) => {\n if (!value) {\n return [];\n }\n if (cache[value]) {\n return cache[value];\n }\n let min = [];\n let newMin;\n let newAmount;\n for (let i = 0; i < coins.length; i++) {\n const coin = coins[i];\n newAmount = value - coin;\n if (newAmount >= 0) {\n newMin = makeChange(newAmount);\n }\n if (\n newAmount >= 0 &&\n (newMin.length < min.length - 1 || !min.length) &&\n (newMin.length || !newAmount)\n ) {\n min = [coin].concat(newMin);\n // console.log('new Min ' + min + ' for ' + amount);\n }\n }\n return (cache[value] = min);\n };\n return makeChange(amount);\n}\n","import { Compare, defaultCompare, DOES_NOT_EXIST } from '../../util';\nimport { quickSort } from '../sorting/quicksort';\n\nfunction binarySearchRecursive(array, value, low, high, compareFn = defaultCompare) {\n if (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const element = array[mid];\n if (compareFn(element, value) === Compare.LESS_THAN) {\n return binarySearchRecursive(array, value, mid + 1, high, compareFn);\n }\n if (compareFn(element, value) === Compare.BIGGER_THAN) {\n return binarySearchRecursive(array, value, low, mid - 1, compareFn);\n }\n return mid;\n }\n return DOES_NOT_EXIST;\n}\n\nexport function binarySearch(array, value, compareFn = defaultCompare) {\n const sortedArray = quickSort(array);\n const low = 0;\n const high = sortedArray.length - 1;\n return binarySearchRecursive(array, value, low, high, compareFn);\n}\n","import { defaultEquals, DOES_NOT_EXIST } from '../../util';\n\nexport function sequentialSearch(array, value, equalsFn = defaultEquals) {\n for (let i = 0; i < array.length; i++) {\n if (equalsFn(value, array[i])) {\n return i;\n }\n }\n return DOES_NOT_EXIST;\n}\n","import {\n biggerEquals,\n Compare,\n defaultCompare,\n defaultEquals,\n defaultDiff,\n DOES_NOT_EXIST,\n lesserEquals\n} from '../../util';\n\nexport function interpolationSearch(\n array,\n value,\n compareFn = defaultCompare,\n equalsFn = defaultEquals,\n diffFn = defaultDiff\n) {\n const { length } = array;\n let low = 0;\n let high = length - 1;\n let position = -1;\n let delta = -1;\n while (\n low <= high &&\n biggerEquals(value, array[low], compareFn) &&\n lesserEquals(value, array[high], compareFn)\n ) {\n delta = diffFn(value, array[low]) / diffFn(array[high], array[low]);\n position = low + Math.floor((high - low) * delta);\n if (equalsFn(array[position], value)) {\n return position;\n }\n if (compareFn(array[position], value) === Compare.LESS_THAN) {\n low = position + 1;\n } else {\n high = position - 1;\n }\n }\n return DOES_NOT_EXIST;\n}\n","import { Compare, defaultCompare, DOES_NOT_EXIST } from '../../util';\nimport { quickSort } from '../sorting/quicksort';\n\nexport function binarySearch(array, value, compareFn = defaultCompare) {\n const sortedArray = quickSort(array);\n let low = 0;\n let high = sortedArray.length - 1;\n while (low <= high) {\n const mid = Math.floor((low + high) / 2);\n const element = sortedArray[mid];\n // console.log('mid element is ' + element);\n if (compareFn(element, value) === Compare.LESS_THAN) {\n low = mid + 1;\n // console.log('low is ' + low);\n } else if (compareFn(element, value) === Compare.BIGGER_THAN) {\n high = mid - 1;\n // console.log('high is ' + high);\n } else {\n // console.log('found it');\n return mid;\n }\n }\n return DOES_NOT_EXIST;\n}\n","import { Compare, defaultCompare } from '../../util';\n\nexport function shellSort(array, compareFn = defaultCompare) {\n let increment = array.length / 2;\n while (increment > 0) {\n for (let i = increment; i < array.length; i++) {\n let j = i;\n const temp = array[i];\n while (j >= increment && compareFn(array[j - increment], temp) === Compare.BIGGER_THAN) {\n array[j] = array[j - increment];\n j -= increment;\n }\n array[j] = temp;\n }\n if (increment === 2) {\n increment = 1;\n } else {\n increment = Math.floor((increment * 5) / 11);\n }\n }\n return array;\n}\n","import { Compare, defaultCompare, swap } from '../../util';\n\nexport const selectionSort = (array, compareFn = defaultCompare) => {\n const { length } = array;\n let indexMin;\n for (let i = 0; i < length - 1; i++) {\n indexMin = i;\n // console.log('index ' + array[i]);\n for (let j = i; j < length; j++) {\n if (compareFn(array[indexMin], array[j]) === Compare.BIGGER_THAN) {\n // console.log('new index min ' + array[j]);\n indexMin = j;\n }\n }\n if (i !== indexMin) {\n // console.log('swap ' + array[i] + ' with ' + array[indexMin]);\n swap(array, i, indexMin);\n }\n }\n return array;\n};\n","import { findMaxValue, findMinValue } from '../search/min-max-search';\n\nconst getBucketIndex = (value, minValue, significantDigit, radixBase) =>\n Math.floor(((value - minValue) / significantDigit) % radixBase);\n\nconst countingSortForRadix = (array, radixBase, significantDigit, minValue) => {\n let bucketsIndex;\n const buckets = [];\n const aux = [];\n for (let i = 0; i < radixBase; i++) {\n buckets[i] = 0;\n }\n for (let i = 0; i < array.length; i++) {\n bucketsIndex = getBucketIndex(array[i], minValue, significantDigit, radixBase);\n buckets[bucketsIndex]++;\n }\n for (let i = 1; i < radixBase; i++) {\n buckets[i] += buckets[i - 1];\n }\n for (let i = array.length - 1; i >= 0; i--) {\n bucketsIndex = getBucketIndex(array[i], minValue, significantDigit, radixBase);\n aux[--buckets[bucketsIndex]] = array[i];\n }\n for (let i = 0; i < array.length; i++) {\n array[i] = aux[i];\n }\n return array;\n};\nexport function radixSort(array, radixBase = 10) {\n if (array.length < 2) {\n return array;\n }\n const minValue = findMinValue(array);\n const maxValue = findMaxValue(array);\n // Perform counting sort for each significant digit, starting at 1\n let significantDigit = 1;\n while ((maxValue - minValue) / significantDigit >= 1) {\n // console.log('radix sort for digit ' + significantDigit);\n array = countingSortForRadix(array, radixBase, significantDigit, minValue);\n // console.log(array.join());\n significantDigit *= radixBase;\n }\n return array;\n}\n","import { Compare, defaultCompare } from '../../util';\n\nfunction merge(left, right, compareFn) {\n let i = 0;\n let j = 0;\n const result = [];\n while (i < left.length && j < right.length) {\n result.push(compareFn(left[i], right[j]) === Compare.LESS_THAN ? left[i++] : right[j++]);\n }\n return result.concat(i < left.length ? left.slice(i) : right.slice(j));\n}\nexport function mergeSort(array, compareFn = defaultCompare) {\n if (array.length > 1) {\n const { length } = array;\n const middle = Math.floor(length / 2);\n const left = mergeSort(array.slice(0, middle), compareFn);\n const right = mergeSort(array.slice(middle, length), compareFn);\n array = merge(left, right, compareFn);\n }\n return array;\n}\n","import { findMaxValue } from '../search/min-max-search';\n\nexport function countingSort(array) {\n if (array.length < 2) {\n return array;\n }\n const maxValue = findMaxValue(array);\n let sortedIndex = 0;\n const counts = new Array(maxValue + 1);\n array.forEach(element => {\n if (!counts[element]) {\n counts[element] = 0;\n }\n counts[element]++;\n });\n // console.log('Frequencies: ' + counts.join());\n counts.forEach((element, i) => {\n while (element > 0) {\n array[sortedIndex++] = i;\n element--;\n }\n });\n return array;\n}\n","import { insertionSort } from './insertion-sort';\n\nfunction createBuckets(array, bucketSize) {\n let minValue = array[0];\n let maxValue = array[0];\n for (let i = 1; i < array.length; i++) {\n if (array[i] < minValue) {\n minValue = array[i];\n } else if (array[i] > maxValue) {\n maxValue = array[i];\n }\n }\n const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1;\n const buckets = [];\n for (let i = 0; i < bucketCount; i++) {\n buckets[i] = [];\n }\n for (let i = 0; i < array.length; i++) {\n buckets[Math.floor((array[i] - minValue) / bucketSize)].push(array[i]);\n }\n return buckets;\n}\nfunction sortBuckets(buckets) {\n const sortedArray = [];\n for (let i = 0; i < buckets.length; i++) {\n if (buckets[i] != null) {\n insertionSort(buckets[i]);\n sortedArray.push(...buckets[i]);\n }\n }\n return sortedArray;\n}\nexport function bucketSort(array, bucketSize = 5) {\n if (array.length < 2) {\n return array;\n }\n const buckets = createBuckets(array, bucketSize);\n return sortBuckets(buckets);\n}\n","import { Compare, defaultCompare, swap } from '../../util';\n\nexport function modifiedBubbleSort(array, compareFn = defaultCompare) {\n const { length } = array;\n for (let i = 0; i < length; i++) {\n // console.log('--- ');\n for (let j = 0; j < length - 1 - i; j++) {\n // console.log('compare ' + array[j] + ' with ' + array[j + 1]);\n if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {\n // console.log('swap ' + array[j] + ' with ' + array[j + 1]);\n swap(array, j, j + 1);\n }\n }\n }\n return array;\n}\n","import { Compare, defaultCompare, swap } from '../../util';\n\nexport function bubbleSort(array, compareFn = defaultCompare) {\n const { length } = array;\n for (let i = 0; i < length; i++) {\n // console.log('--- ');\n for (let j = 0; j < length - 1; j++) {\n // console.log('compare ' + array[j] + ' with ' + array[j + 1]);\n if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) {\n // console.log('swap ' + array[j] + ' with ' + array[j + 1]);\n swap(array, j, j + 1);\n }\n }\n }\n return array;\n}\n","import { swap } from '../../util';\n\nexport function shuffle(array) {\n let currentIndex = array.length;\n while (currentIndex !== 0) {\n const randomIndex = Math.floor(Math.random() * currentIndex);\n currentIndex--;\n swap(array, currentIndex, randomIndex);\n }\n return array;\n}\n","const INF = Number.MAX_SAFE_INTEGER;\nconst find = (i, parent) => {\n while (parent[i]) {\n i = parent[i]; // eslint-disable-line prefer-destructuring\n }\n return i;\n};\nconst union = (i, j, parent) => {\n if (i !== j) {\n parent[j] = i;\n return true;\n }\n return false;\n};\nconst initializeCost = graph => {\n const cost = [];\n const { length } = graph;\n for (let i = 0; i < length; i++) {\n cost[i] = [];\n for (let j = 0; j < length; j++) {\n if (graph[i][j] === 0) {\n cost[i][j] = INF;\n } else {\n cost[i][j] = graph[i][j];\n }\n }\n }\n return cost;\n};\nexport const kruskal = graph => {\n const { length } = graph;\n const parent = [];\n let ne = 0;\n let a;\n let b;\n let u;\n let v;\n const cost = initializeCost(graph);\n while (ne < length - 1) {\n for (let i = 0, min = INF; i < length; i++) {\n for (let j = 0; j < length; j++) {\n if (cost[i][j] < min) {\n min = cost[i][j];\n a = u = i;\n b = v = j;\n }\n }\n }\n u = find(u, parent);\n v = find(v, parent);\n if (union(u, v, parent)) {\n ne++;\n }\n cost[a][b] = cost[b][a] = INF;\n }\n return parent;\n};\n","const INF = Number.MAX_SAFE_INTEGER;\nconst minKey = (graph, key, visited) => {\n // Initialize min value\n let min = INF;\n let minIndex = 0;\n for (let v = 0; v < graph.length; v++) {\n if (visited[v] === false && key[v] < min) {\n min = key[v];\n minIndex = v;\n }\n }\n return minIndex;\n};\nexport const prim = graph => {\n const parent = [];\n const key = [];\n const visited = [];\n const { length } = graph;\n for (let i = 0; i < length; i++) {\n key[i] = INF;\n visited[i] = false;\n }\n key[0] = 0;\n parent[0] = -1;\n for (let i = 0; i < length - 1; i++) {\n const u = minKey(graph, key, visited);\n visited[u] = true;\n for (let v = 0; v < length; v++) {\n if (graph[u][v] && !visited[v] && graph[u][v] < key[v]) {\n parent[v] = u;\n key[v] = graph[u][v];\n }\n }\n }\n return parent;\n};\n","const INF = Number.MAX_SAFE_INTEGER;\nconst minDistance = (dist, visited) => {\n let min = INF;\n let minIndex = -1;\n for (let v = 0; v < dist.length; v++) {\n if (visited[v] === false && dist[v] <= min) {\n min = dist[v];\n minIndex = v;\n }\n }\n return minIndex;\n};\nexport const dijkstra = (graph, src) => {\n const dist = [];\n const visited = [];\n const { length } = graph;\n for (let i = 0; i < length; i++) {\n dist[i] = INF;\n visited[i] = false;\n }\n dist[src] = 0;\n for (let i = 0; i < length - 1; i++) {\n const u = minDistance(dist, visited);\n visited[u] = true;\n for (let v = 0; v < length; v++) {\n if (!visited[v] && graph[u][v] !== 0 && dist[u] !== INF && dist[u] + graph[u][v] < dist[v]) {\n dist[v] = dist[u] + graph[u][v];\n }\n }\n }\n return dist;\n};\n","// import Graph from '../../data-structures/graph';\n\nconst Colors = {\n WHITE: 0,\n GREY: 1,\n BLACK: 2\n};\n\nconst initializeColor = vertices => {\n const color = {};\n for (let i = 0; i < vertices.length; i++) {\n color[vertices[i]] = Colors.WHITE;\n }\n return color;\n};\n\nconst depthFirstSearchVisit = (u, color, adjList, callback) => {\n color[u] = Colors.GREY;\n if (callback) {\n callback(u);\n }\n // console.log('Discovered ' + u);\n const neighbors = adjList.get(u);\n for (let i = 0; i < neighbors.length; i++) {\n const w = neighbors[i];\n if (color[w] === Colors.WHITE) {\n depthFirstSearchVisit(w, color, adjList, callback);\n }\n }\n color[u] = Colors.BLACK;\n // console.log('explored ' + u);\n};\n\nexport const depthFirstSearch = (graph, callback) => {\n const vertices = graph.getVertices();\n const adjList = graph.getAdjList();\n const color = initializeColor(vertices);\n\n for (let i = 0; i < vertices.length; i++) {\n if (color[vertices[i]] === Colors.WHITE) {\n depthFirstSearchVisit(vertices[i], color, adjList, callback);\n }\n }\n};\n\nconst DFSVisit = (u, color, d, f, p, time, adjList) => {\n // console.log('discovered ' + u);\n color[u] = Colors.GREY;\n d[u] = ++time.count;\n const neighbors = adjList.get(u);\n for (let i = 0; i < neighbors.length; i++) {\n const w = neighbors[i];\n if (color[w] === Colors.WHITE) {\n p[w] = u;\n DFSVisit(w, color, d, f, p, time, adjList);\n }\n }\n color[u] = Colors.BLACK;\n f[u] = ++time.count;\n // console.log('explored ' + u);\n};\n\nexport const DFS = graph => {\n const vertices = graph.getVertices();\n const adjList = graph.getAdjList();\n const color = initializeColor(vertices);\n const d = {};\n const f = {};\n const p = {};\n const time = { count: 0 };\n for (let i = 0; i < vertices.length; i++) {\n f[vertices[i]] = 0;\n d[vertices[i]] = 0;\n p[vertices[i]] = null;\n }\n for (let i = 0; i < vertices.length; i++) {\n if (color[vertices[i]] === Colors.WHITE) {\n DFSVisit(vertices[i], color, d, f, p, time, adjList);\n }\n }\n return {\n discovery: d,\n finished: f,\n predecessors: p\n };\n};\n","import Queue from '../../data-structures/queue';\n\nconst Colors = {\n WHITE: 0,\n GREY: 1,\n BLACK: 2\n};\n\nconst initializeColor = vertices => {\n const color = {};\n for (let i = 0; i < vertices.length; i++) {\n color[vertices[i]] = Colors.WHITE;\n }\n return color;\n};\n\nexport const breadthFirstSearch = (graph, startVertex, callback) => {\n const vertices = graph.getVertices();\n const adjList = graph.getAdjList();\n const color = initializeColor(vertices);\n const queue = new Queue();\n\n queue.enqueue(startVertex);\n\n while (!queue.isEmpty()) {\n const u = queue.dequeue();\n const neighbors = adjList.get(u);\n color[u] = Colors.GREY;\n for (let i = 0; i < neighbors.length; i++) {\n const w = neighbors[i];\n if (color[w] === Colors.WHITE) {\n color[w] = Colors.GREY;\n queue.enqueue(w);\n }\n }\n color[u] = Colors.BLACK;\n if (callback) {\n callback(u);\n }\n }\n};\n\nexport const BFS = (graph, startVertex) => {\n const vertices = graph.getVertices();\n const adjList = graph.getAdjList();\n const color = initializeColor(vertices);\n const queue = new Queue();\n const distances = {};\n const predecessors = {};\n queue.enqueue(startVertex);\n for (let i = 0; i < vertices.length; i++) {\n distances[vertices[i]] = 0;\n predecessors[vertices[i]] = null;\n }\n while (!queue.isEmpty()) {\n const u = queue.dequeue();\n const neighbors = adjList.get(u);\n color[u] = Colors.GREY;\n for (let i = 0; i < neighbors.length; i++) {\n const w = neighbors[i];\n if (color[w] === Colors.WHITE) {\n color[w] = Colors.GREY;\n distances[w] = distances[u] + 1;\n predecessors[w] = u;\n queue.enqueue(w);\n }\n }\n color[u] = Colors.BLACK;\n }\n return {\n distances,\n predecessors\n };\n};\n","import Dictionary from './dictionary';\n\nexport default class Graph {\n constructor(isDirected = false) {\n this.isDirected = isDirected;\n this.vertices = [];\n this.adjList = new Dictionary();\n }\n addVertex(v) {\n if (!this.vertices.includes(v)) {\n this.vertices.push(v);\n this.adjList.set(v, []); // initialize adjacency list with array as well;\n }\n }\n addEdge(a, b) {\n if (!this.adjList.get(a)) {\n this.addVertex(a);\n }\n if (!this.adjList.get(b)) {\n this.addVertex(b);\n }\n this.adjList.get(a).push(b);\n if (this.isDirected !== true) {\n this.adjList.get(b).push(a);\n }\n }\n getVertices() {\n return this.vertices;\n }\n getAdjList() {\n return this.adjList;\n }\n toString() {\n let s = '';\n for (let i = 0; i < this.vertices.length; i++) {\n s += `${this.vertices[i]} -> `;\n const neighbors = this.adjList.get(this.vertices[i]);\n for (let j = 0; j < neighbors.length; j++) {\n s += `${neighbors[j]} `;\n }\n s += '\\n';\n }\n return s;\n }\n}\n","import { defaultCompare, swap } from '../../util';\n\nfunction heapify(array, index, heapSize, compareFn) {\n let largest = index;\n const left = (2 * index) + 1;\n const right = (2 * index) + 2;\n if (left < heapSize && compareFn(array[left], array[index]) > 0) {\n largest = left;\n }\n if (right < heapSize && compareFn(array[right], array[largest]) > 0) {\n largest = right;\n }\n if (largest !== index) {\n swap(array, index, largest);\n heapify(array, largest, heapSize, compareFn);\n }\n}\n\nfunction buildMaxHeap(array, compareFn) {\n for (let i = Math.floor(array.length / 2); i >= 0; i -= 1) {\n heapify(array, i, array.length, compareFn);\n }\n return array;\n}\n\nexport default function heapSort(array, compareFn = defaultCompare) {\n let heapSize = array.length;\n buildMaxHeap(array, compareFn);\n while (heapSize > 1) {\n swap(array, 0, --heapSize);\n heapify(array, 0, heapSize, compareFn);\n }\n return array;\n}\n","import { Compare, defaultCompare, reverseCompare, swap } from '../util';\n\nexport class MinHeap {\n constructor(compareFn = defaultCompare) {\n this.compareFn = compareFn;\n this.heap = [];\n }\n getLeftIndex(index) {\n return (2 * index) + 1;\n }\n getRightIndex(index) {\n return (2 * index) + 2;\n }\n getParentIndex(index) {\n if (index === 0) {\n return undefined;\n }\n return Math.floor((index - 1) / 2);\n }\n size() {\n return this.heap.length;\n }\n isEmpty() {\n return this.size() <= 0;\n }\n clear() {\n this.heap = [];\n }\n findMinimum() {\n return this.isEmpty() ? undefined : this.heap[0];\n }\n insert(value) {\n if (value != null) {\n const index = this.heap.length;\n this.heap.push(value);\n this.siftUp(index);\n return true;\n }\n return false;\n }\n siftDown(index) {\n let element = index;\n const left = this.getLeftIndex(index);\n const right = this.getRightIndex(index);\n const size = this.size();\n if (\n left < size &&\n this.compareFn(this.heap[element], this.heap[left]) === Compare.BIGGER_THAN\n ) {\n element = left;\n }\n if (\n right < size &&\n this.compareFn(this.heap[element], this.heap[right]) === Compare.BIGGER_THAN\n ) {\n element = right;\n }\n if (index !== element) {\n swap(this.heap, index, element);\n this.siftDown(element);\n }\n }\n siftUp(index) {\n let parent = this.getParentIndex(index);\n while (\n index > 0 &&\n this.compareFn(this.heap[parent], this.heap[index]) === Compare.BIGGER_THAN\n ) {\n swap(this.heap, parent, index);\n index = parent;\n parent = this.getParentIndex(index);\n }\n }\n extract() {\n if (this.isEmpty()) {\n return undefined;\n }\n if (this.size() === 1) {\n return this.heap.shift();\n }\n const removedValue = this.heap[0];\n this.heap[0] = this.heap.pop();\n this.siftDown(0);\n return removedValue;\n }\n heapify(array) {\n if (array) {\n this.heap = array;\n }\n const maxIndex = Math.floor(this.size() / 2) - 1;\n for (let i = 0; i <= maxIndex; i++) {\n this.siftDown(i);\n }\n return this.heap;\n }\n getAsArray() {\n return this.heap;\n }\n}\nexport class MaxHeap extends MinHeap {\n constructor(compareFn = defaultCompare) {\n super(compareFn);\n this.compareFn = compareFn;\n this.compareFn = reverseCompare(compareFn);\n }\n}\n","import { Compare, defaultCompare } from '../util';\nimport BinarySearchTree from './binary-search-tree';\nimport { Node } from './models/node';\n\nconst BalanceFactor = {\n UNBALANCED_RIGHT: 1,\n SLIGHTLY_UNBALANCED_RIGHT: 2,\n BALANCED: 3,\n SLIGHTLY_UNBALANCED_LEFT: 4,\n UNBALANCED_LEFT: 5\n};\n\nexport default class AVLTree extends BinarySearchTree {\n constructor(compareFn = defaultCompare) {\n super(compareFn);\n this.compareFn = compareFn;\n this.root = null;\n }\n getNodeHeight(node) {\n if (node == null) {\n return -1;\n }\n return Math.max(this.getNodeHeight(node.left), this.getNodeHeight(node.right)) + 1;\n }\n /**\n * Left left case: rotate right\n *\n * b a\n * / \\ / \\\n * a e -> rotationLL(b) -> c b\n * / \\ / \\\n * c d d e\n *\n * @param node Node\n */\n rotationLL(node) {\n const tmp = node.left;\n node.left = tmp.right;\n tmp.right = node;\n return tmp;\n }\n /**\n * Right right case: rotate left\n *\n * a b\n * / \\ / \\\n * c b -> rotationRR(a) -> a e\n * / \\ / \\\n * d e c d\n *\n * @param node Node\n */\n rotationRR(node) {\n const tmp = node.right;\n node.right = tmp.left;\n tmp.left = node;\n return tmp;\n }\n /**\n * Left right case: rotate left then right\n * @param node Node\n */\n rotationLR(node) {\n node.left = this.rotationRR(node.left);\n return this.rotationLL(node);\n }\n /**\n * Right left case: rotate right then left\n * @param node Node\n */\n rotationRL(node) {\n node.right = this.rotationLL(node.right);\n return this.rotationRR(node);\n }\n getBalanceFactor(node) {\n const heightDifference = this.getNodeHeight(node.left) - this.getNodeHeight(node.right);\n switch (heightDifference) {\n case -2:\n return BalanceFactor.UNBALANCED_RIGHT;\n case -1:\n return BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT;\n case 1:\n return BalanceFactor.SLIGHTLY_UNBALANCED_LEFT;\n case 2:\n return BalanceFactor.UNBALANCED_LEFT;\n default:\n return BalanceFactor.BALANCED;\n }\n }\n insert(key) {\n this.root = this.insertNode(this.root, key);\n }\n insertNode(node, key) {\n if (node == null) {\n return new Node(key);\n } else if (this.compareFn(key, node.key) === Compare.LESS_THAN) {\n node.left = this.insertNode(node.left, key);\n } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) {\n node.right = this.insertNode(node.right, key);\n } else {\n return node; // duplicated key\n }\n // verify if tree is balanced\n const balanceFactor = this.getBalanceFactor(node);\n if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {\n if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) {\n // Left left case\n node = this.rotationLL(node);\n } else {\n // Left right case\n return this.rotationLR(node);\n }\n }\n if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {\n if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) {\n // Right right case\n node = this.rotationRR(node);\n } else {\n // Right left case\n return this.rotationRL(node);\n }\n }\n return node;\n }\n removeNode(node, key) {\n node = super.removeNode(node, key); // {1}\n if (node == null) {\n return node;\n }\n // verify if tree is balanced\n const balanceFactor = this.getBalanceFactor(node);\n if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) {\n // Left left case\n if (\n this.getBalanceFactor(node.left) === BalanceFactor.BALANCED ||\n this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT\n ) {\n return this.rotationLL(node);\n }\n // Left right case\n if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) {\n return this.rotationLR(node.left);\n }\n }\n if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) {\n // Right right case\n if (\n this.getBalanceFactor(node.right) === BalanceFactor.BALANCED ||\n this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT\n ) {\n return this.rotationRR(node);\n }\n // Right left case\n if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) {\n return this.rotationRL(node.right);\n }\n }\n return node;\n }\n}\n","export function fibonacci(n) {\n if (n < 1) {\n return 0;\n }\n if (n <= 2) {\n return 1;\n }\n return fibonacci(n - 1) + fibonacci(n - 2);\n}\n\nexport function fibonacciIterative(n) {\n if (n < 1) { return 0; }\n let fibNMinus2 = 0;\n let fibNMinus1 = 1;\n let fibN = n;\n for (let i = 2; i <= n; i++) {\n fibN = fibNMinus1 + fibNMinus2;\n fibNMinus2 = fibNMinus1;\n fibNMinus1 = fibN;\n }\n return fibN;\n}\n\nexport function fibonacciMemoization(n) {\n if (n < 1) { return 0; }\n const memo = [0, 1];\n const fibonacciMem = num => {\n if (memo[num] != null) { return memo[num]; }\n return (memo[num] = fibonacciMem(num - 1) + fibonacciMem(num - 2));\n };\n return fibonacciMem(n);\n}\n","export function factorialIterative(number) {\n if (number < 0) {\n return undefined;\n }\n let total = 1;\n for (let n = number; n > 1; n--) {\n total *= n;\n }\n return total;\n}\n\nexport function factorial(n) {\n if (n < 0) {\n return undefined;\n }\n if (n === 1 || n === 0) {\n return 1;\n }\n return n * factorial(n - 1);\n}\n","import { ValuePair } from './value-pair';\n\nexport class ValuePairLazy extends ValuePair {\n constructor(key, value, isDeleted = false) {\n super(key, value);\n this.key = key;\n this.value = value;\n this.isDeleted = isDeleted;\n }\n}\n","import { defaultToString } from '../util';\nimport { ValuePairLazy } from './models/value-pair-lazy';\n\nexport default class HashTableLinearProbingLazy {\n constructor(toStrFn = defaultToString) {\n this.toStrFn = toStrFn;\n this.table = {};\n }\n loseloseHashCode(key) {\n if (typeof key === 'number') {\n return key;\n }\n const tableKey = this.toStrFn(key);\n let hash = 0;\n for (let i = 0; i < tableKey.length; i++) {\n hash += tableKey.charCodeAt(i);\n }\n return hash % 37;\n }\n hashCode(key) {\n return this.loseloseHashCode(key);\n }\n put(key, value) {\n if (key != null && value != null) {\n const position = this.hashCode(key);\n if (\n this.table[position] == null ||\n (this.table[position] != null && this.table[position].isDeleted)\n ) {\n this.table[position] = new ValuePairLazy(key, value);\n } else {\n let index = position + 1;\n while (this.table[index] != null && !this.table[position].isDeleted) {\n index++;\n }\n this.table[index] = new ValuePairLazy(key, value);\n }\n return true;\n }\n return false;\n }\n get(key) {\n const position = this.hashCode(key);\n if (this.table[position] != null) {\n if (this.table[position].key === key && !this.table[position].isDeleted) {\n return this.table[position].value;\n }\n let index = position + 1;\n while (\n this.table[index] != null &&\n (this.table[index].key !== key || this.table[index].isDeleted)\n ) {\n if (this.table[index].key === key && this.table[index].isDeleted) {\n return undefined;\n }\n index++;\n }\n if (\n this.table[index] != null &&\n this.table[index].key === key &&\n !this.table[index].isDeleted\n ) {\n return this.table[position].value;\n }\n }\n return undefined;\n }\n remove(key) {\n const position = this.hashCode(key);\n if (this.table[position] != null) {\n if (this.table[position].key === key && !this.table[position].isDeleted) {\n this.table[position].isDeleted = true;\n return true;\n }\n let index = position + 1;\n while (\n this.table[index] != null &&\n (this.table[index].key !== key || this.table[index].isDeleted)\n ) {\n index++;\n }\n if (\n this.table[index] != null &&\n this.table[index].key === key &&\n !this.table[index].isDeleted\n ) {\n this.table[index].isDeleted = true;\n return true;\n }\n }\n return false;\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n let count = 0;\n Object.values(this.table).forEach(valuePair => {\n count += valuePair.isDeleted === true ? 0 : 1;\n });\n return count;\n }\n clear() {\n this.table = {};\n }\n getTable() {\n return this.table;\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n const keys = Object.keys(this.table);\n let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`;\n for (let i = 1; i < keys.length; i++) {\n objString = `${objString},{${keys[i]} => ${this.table[\n keys[i]\n ].toString()}}`;\n }\n return objString;\n }\n}\n","import { defaultToString } from '../util';\nimport { ValuePair } from './models/value-pair';\n\nexport default class HashTableLinearProbing {\n constructor(toStrFn = defaultToString) {\n this.toStrFn = toStrFn;\n this.table = {};\n }\n loseloseHashCode(key) {\n if (typeof key === 'number') {\n return key;\n }\n const tableKey = this.toStrFn(key);\n let hash = 0;\n for (let i = 0; i < tableKey.length; i++) {\n hash += tableKey.charCodeAt(i);\n }\n return hash % 37;\n }\n hashCode(key) {\n return this.loseloseHashCode(key);\n }\n put(key, value) {\n if (key != null && value != null) {\n const position = this.hashCode(key);\n if (this.table[position] == null) {\n this.table[position] = new ValuePair(key, value);\n } else {\n let index = position + 1;\n while (this.table[index] != null) {\n index++;\n }\n this.table[index] = new ValuePair(key, value);\n }\n return true;\n }\n return false;\n }\n get(key) {\n const position = this.hashCode(key);\n if (this.table[position] != null) {\n if (this.table[position].key === key) {\n return this.table[position].value;\n }\n let index = position + 1;\n while (this.table[index] != null && this.table[index].key !== key) {\n index++;\n }\n if (this.table[index] != null && this.table[index].key === key) {\n return this.table[position].value;\n }\n }\n return undefined;\n }\n remove(key) {\n const position = this.hashCode(key);\n if (this.table[position] != null) {\n if (this.table[position].key === key) {\n delete this.table[position];\n this.verifyRemoveSideEffect(key, position);\n return true;\n }\n let index = position + 1;\n while (this.table[index] != null && this.table[index].key !== key) {\n index++;\n }\n if (this.table[index] != null && this.table[index].key === key) {\n delete this.table[index];\n this.verifyRemoveSideEffect(key, index);\n return true;\n }\n }\n return false;\n }\n verifyRemoveSideEffect(key, removedPosition) {\n const hash = this.hashCode(key);\n let index = removedPosition + 1;\n while (this.table[index] != null) {\n const posHash = this.hashCode(this.table[index].key);\n if (posHash <= hash || posHash <= removedPosition) {\n this.table[removedPosition] = this.table[index];\n delete this.table[index];\n removedPosition = index;\n }\n index++;\n }\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n return Object.keys(this.table).length;\n }\n clear() {\n this.table = {};\n }\n getTable() {\n return this.table;\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n const keys = Object.keys(this.table);\n let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`;\n for (let i = 1; i < keys.length; i++) {\n objString = `${objString},{${keys[i]} => ${this.table[\n keys[i]\n ].toString()}}`;\n }\n return objString;\n }\n}\n","import { defaultToString } from '../util';\nimport LinkedList from './linked-list';\nimport { ValuePair } from './models/value-pair';\n\nexport default class HashTableSeparateChaining {\n constructor(toStrFn = defaultToString) {\n this.toStrFn = toStrFn;\n this.table = {};\n }\n loseloseHashCode(key) {\n if (typeof key === 'number') {\n return key;\n }\n const tableKey = this.toStrFn(key);\n let hash = 0;\n for (let i = 0; i < tableKey.length; i++) {\n hash += tableKey.charCodeAt(i);\n }\n return hash % 37;\n }\n hashCode(key) {\n return this.loseloseHashCode(key);\n }\n put(key, value) {\n if (key != null && value != null) {\n const position = this.hashCode(key);\n if (this.table[position] == null) {\n this.table[position] = new LinkedList();\n }\n this.table[position].push(new ValuePair(key, value));\n return true;\n }\n return false;\n }\n get(key) {\n const position = this.hashCode(key);\n const linkedList = this.table[position];\n if (linkedList != null && !linkedList.isEmpty()) {\n let current = linkedList.getHead();\n while (current != null) {\n if (current.element.key === key) {\n return current.element.value;\n }\n current = current.next;\n }\n }\n return undefined;\n }\n remove(key) {\n const position = this.hashCode(key);\n const linkedList = this.table[position];\n if (linkedList != null && !linkedList.isEmpty()) {\n let current = linkedList.getHead();\n while (current != null) {\n if (current.element.key === key) {\n linkedList.remove(current.element);\n if (linkedList.isEmpty()) {\n delete this.table[position];\n }\n return true;\n }\n current = current.next;\n }\n }\n return false;\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n let count = 0;\n Object.values(this.table).forEach(linkedList => {\n count += linkedList.size();\n });\n return count;\n }\n clear() {\n this.table = {};\n }\n getTable() {\n return this.table;\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n const keys = Object.keys(this.table);\n let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`;\n for (let i = 1; i < keys.length; i++) {\n objString = `${objString},{${keys[i]} => ${this.table[\n keys[i]\n ].toString()}}`;\n }\n return objString;\n }\n}\n","import { defaultToString } from '../util';\nimport { ValuePair } from './models/value-pair';\n\nexport default class HashTable {\n constructor(toStrFn = defaultToString) {\n this.toStrFn = toStrFn;\n this.table = {};\n }\n loseloseHashCode(key) {\n if (typeof key === 'number') {\n return key;\n }\n const tableKey = this.toStrFn(key);\n let hash = 0;\n for (let i = 0; i < tableKey.length; i++) {\n hash += tableKey.charCodeAt(i);\n }\n return hash % 37;\n }\n /* djb2HashCode(key) {\n const tableKey = this.toStrFn(key);\n let hash = 5381;\n for (let i = 0; i < tableKey.length; i++) {\n hash = (hash * 33) + tableKey.charCodeAt(i);\n }\n return hash % 1013;\n } */\n hashCode(key) {\n return this.loseloseHashCode(key);\n }\n put(key, value) {\n if (key != null && value != null) {\n const position = this.hashCode(key);\n this.table[position] = new ValuePair(key, value);\n return true;\n }\n return false;\n }\n get(key) {\n const valuePair = this.table[this.hashCode(key)];\n return valuePair == null ? undefined : valuePair.value;\n }\n remove(key) {\n const hash = this.hashCode(key);\n const valuePair = this.table[hash];\n if (valuePair != null) {\n delete this.table[hash];\n return true;\n }\n return false;\n }\n getTable() {\n return this.table;\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n return Object.keys(this.table).length;\n }\n clear() {\n this.table = {};\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n const keys = Object.keys(this.table);\n let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`;\n for (let i = 1; i < keys.length; i++) {\n objString = `${objString},{${keys[i]} => ${this.table[keys[i]].toString()}}`;\n }\n return objString;\n }\n}\n","export default class Set {\n constructor() {\n this.items = {};\n }\n add(element) {\n if (!this.has(element)) {\n this.items[element] = element;\n return true;\n }\n return false;\n }\n delete(element) {\n if (this.has(element)) {\n delete this.items[element];\n return true;\n }\n return false;\n }\n has(element) {\n return Object.prototype.hasOwnProperty.call(this.items, element);\n }\n values() {\n return Object.values(this.items);\n }\n union(otherSet) {\n const unionSet = new Set();\n this.values().forEach(value => unionSet.add(value));\n otherSet.values().forEach(value => unionSet.add(value));\n return unionSet;\n }\n intersection(otherSet) {\n const intersectionSet = new Set();\n const values = this.values();\n const otherValues = otherSet.values();\n let biggerSet = values;\n let smallerSet = otherValues;\n if (otherValues.length - values.length > 0) {\n biggerSet = otherValues;\n smallerSet = values;\n }\n smallerSet.forEach(value => {\n if (biggerSet.includes(value)) {\n intersectionSet.add(value);\n }\n });\n return intersectionSet;\n }\n difference(otherSet) {\n const differenceSet = new Set();\n this.values().forEach(value => {\n if (!otherSet.has(value)) {\n differenceSet.add(value);\n }\n });\n return differenceSet;\n }\n isSubsetOf(otherSet) {\n if (this.size() > otherSet.size()) {\n return false;\n }\n let isSubset = true;\n this.values().every(value => {\n if (!otherSet.has(value)) {\n isSubset = false;\n return false;\n }\n return true;\n });\n return isSubset;\n }\n isEmpty() {\n return this.size() === 0;\n }\n size() {\n return Object.keys(this.items).length;\n }\n clear() {\n this.items = {};\n }\n toString() {\n if (this.isEmpty()) {\n return '';\n }\n const values = this.values();\n let objString = `${values[0]}`;\n for (let i = 1; i < values.length; i++) {\n objString = `${objString},${values[i].toString()}`;\n }\n return objString;\n }\n}\n","import DoublyLinkedList from './doubly-linked-list';\n\nexport default class StackLinkedList {\n constructor() {\n this.items = new DoublyLinkedList();\n }\n push(element) {\n this.items.push(element);\n }\n pop() {\n if (this.isEmpty()) {\n return undefined;\n }\n const result = this.items.removeAt(this.size() - 1);\n return result;\n }\n peek() {\n if (this.isEmpty()) {\n return undefined;\n }\n return this.items.getElementAt(this.size() - 1).element;\n }\n isEmpty() {\n return this.items.isEmpty();\n }\n size() {\n return this.items.size();\n }\n clear() {\n this.items.clear();\n }\n toString() {\n return this.items.toString();\n }\n}\n","import { Compare, defaultCompare, defaultEquals } from '../util';\nimport LinkedList from './linked-list';\n\nexport default class SortedLinkedList extends LinkedList {\n constructor(equalsFn = defaultEquals, compareFn = defaultCompare) {\n super(equalsFn);\n this.equalsFn = equalsFn;\n this.compareFn = compareFn;\n }\n push(element) {\n if (this.isEmpty()) {\n super.push(element);\n } else {\n const index = this.getIndexNextSortedElement(element);\n super.insert(element, index);\n }\n }\n insert(element, index = 0) {\n if (this.isEmpty()) {\n return super.insert(element, index === 0 ? index : 0);\n }\n const pos = this.getIndexNextSortedElement(element);\n return super.insert(element, pos);\n }\n getIndexNextSortedElement(element) {\n let current = this.head;\n let i = 0;\n for (; i < this.size() && current; i++) {\n const comp = this.compareFn(element, current.element);\n if (comp === Compare.LESS_THAN) {\n return i;\n }\n current = current.next;\n }\n return i;\n }\n}\n","import { defaultEquals } from '../util';\nimport LinkedList from './linked-list';\nimport { Node } from './models/linked-list-models';\n\nexport default class CircularLinkedList extends LinkedList {\n constructor(equalsFn = defaultEquals) {\n super(equalsFn);\n }\n push(element) {\n const node = new Node(element);\n let current;\n if (this.head == null) {\n this.head = node;\n } else {\n current = this.getElementAt(this.size() - 1);\n current.next = node;\n }\n // set node.next to head - to have circular list\n node.next = this.head;\n this.count++;\n }\n insert(element, index) {\n if (index >= 0 && index <= this.count) {\n const node = new Node(element);\n let current = this.head;\n if (index === 0) {\n if (this.head == null) {\n // if no node in list\n this.head = node;\n node.next = this.head;\n } else {\n node.next = current;\n current = this.getElementAt(this.size());\n // update last element\n this.head = node;\n current.next = this.head;\n }\n } else {\n const previous = this.getElementAt(index - 1);\n node.next = previous.next;\n previous.next = node;\n }\n this.count++;\n return true;\n }\n return false;\n }\n removeAt(index) {\n if (index >= 0 && index < this.count) {\n let current = this.head;\n if (index === 0) {\n if (this.size() === 1) {\n this.head = undefined;\n } else {\n const removed = this.head;\n current = this.getElementAt(this.size() - 1);\n this.head = this.head.next;\n current.next = this.head;\n current = removed;\n }\n } else {\n // no need to update last element for circular list\n const previous = this.getElementAt(index - 1);\n current = previous.next;\n previous.next = current.next;\n }\n this.count--;\n return current.element;\n }\n return undefined;\n }\n}\n","import Deque from '../data-structures/deque';\n\nexport function palindromeChecker(aString) {\n if (\n aString === undefined ||\n aString === null ||\n (aString !== null && aString.length === 0)\n ) {\n return false;\n }\n const deque = new Deque();\n const lowerString = aString.toLocaleLowerCase().split(' ').join('');\n let firstChar;\n let lastChar;\n\n for (let i = 0; i < lowerString.length; i++) {\n deque.addBack(lowerString.charAt(i));\n }\n\n while (deque.size() > 1) {\n firstChar = deque.removeFront();\n lastChar = deque.removeBack();\n if (firstChar !== lastChar) {\n return false;\n }\n }\n\n return true;\n}\n","import Queue from '../data-structures/queue';\n\nexport function hotPotato(elementsList, num) {\n const queue = new Queue();\n const elimitatedList = [];\n\n for (let i = 0; i < elementsList.length; i++) {\n queue.enqueue(elementsList[i]);\n }\n\n while (queue.size() > 1) {\n for (let i = 0; i < num; i++) {\n queue.enqueue(queue.dequeue());\n }\n elimitatedList.push(queue.dequeue());\n }\n\n return {\n eliminated: elimitatedList,\n winner: queue.dequeue()\n };\n}\n","// @ts-check\nimport Stack from '../data-structures/stack';\n\nexport function parenthesesChecker(symbols) {\n const stack = new Stack();\n const opens = '([{';\n const closers = ')]}';\n let balanced = true;\n let index = 0;\n let symbol;\n let top;\n\n while (index < symbols.length && balanced) {\n symbol = symbols[index];\n if (opens.indexOf(symbol) >= 0) {\n stack.push(symbol);\n } else if (stack.isEmpty()) {\n balanced = false;\n } else {\n top = stack.pop();\n if (!(opens.indexOf(top) === closers.indexOf(symbol))) {\n balanced = false;\n }\n }\n index++;\n }\n return balanced && stack.isEmpty();\n}\n","// @ts-check\nimport Stack from '../data-structures/stack';\n\nexport function decimalToBinary(decNumber) {\n const remStack = new Stack();\n let number = decNumber;\n let rem;\n let binaryString = '';\n\n while (number > 0) {\n rem = Math.floor(number % 2);\n remStack.push(rem);\n number = Math.floor(number / 2);\n }\n\n while (!remStack.isEmpty()) {\n binaryString += remStack.pop().toString();\n }\n\n return binaryString;\n}\n\nexport function baseConverter(decNumber, base) {\n const remStack = new Stack();\n const digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';\n let number = decNumber;\n let rem;\n let baseString = '';\n\n if (!(base >= 2 && base <= 36)) {\n return '';\n }\n\n while (number > 0) {\n rem = Math.floor(number % base);\n remStack.push(rem);\n number = Math.floor(number / base);\n }\n\n while (!remStack.isEmpty()) {\n baseString += digits[remStack.pop()];\n }\n\n return baseString;\n}\n","// @ts-check\nimport Stack from '../data-structures/stack';\n\nfunction towerOfHanoi(plates, source, helper, dest, sourceName, helperName, destName, moves = []) {\n if (plates <= 0) {\n return moves;\n }\n if (plates === 1) {\n dest.push(source.pop());\n const move = {};\n move[sourceName] = source.toString();\n move[helperName] = helper.toString();\n move[destName] = dest.toString();\n moves.push(move);\n } else {\n towerOfHanoi(plates - 1, source, dest, helper, sourceName, destName, helperName, moves);\n dest.push(source.pop());\n const move = {};\n move[sourceName] = source.toString();\n move[helperName] = helper.toString();\n move[destName] = dest.toString();\n moves.push(move);\n towerOfHanoi(plates - 1, helper, source, dest, helperName, sourceName, destName, moves);\n }\n return moves;\n}\n\nexport function hanoiStack(plates) {\n const source = new Stack();\n const dest = new Stack();\n const helper = new Stack();\n\n for (let i = plates; i > 0; i--) {\n source.push(i);\n }\n\n return towerOfHanoi(plates, source, helper, dest, 'source', 'helper', 'dest');\n}\n\nexport function hanoi(plates, source, helper, dest, moves = []) {\n if (plates <= 0) {\n return moves;\n }\n if (plates === 1) {\n moves.push([source, dest]);\n } else {\n hanoi(plates - 1, source, dest, helper, moves);\n moves.push([source, dest]);\n hanoi(plates - 1, helper, source, dest, moves);\n }\n return moves;\n}\n","// @ts-check\n\nexport default class StackArray {\n constructor() {\n this.items = [];\n }\n push(element) {\n this.items.push(element);\n }\n\n pop() {\n return this.items.pop();\n }\n\n peek() {\n return this.items[this.items.length - 1];\n }\n\n isEmpty() {\n return this.items.length === 0;\n }\n\n size() {\n return this.items.length;\n }\n\n clear() {\n this.items = [];\n }\n\n toArray() {\n return this.items;\n }\n\n toString() {\n return this.items.toString();\n }\n}\n","import * as _util from './util';\n\n// chapters 05 and 07\nexport const util = _util;\n\n// chapter 03\nexport { default as StackArray } from './data-structures/stack-array';\nexport { default as Stack } from './data-structures/stack';\nexport { hanoi } from './others/hanoi';\nexport { hanoiStack } from './others/hanoi';\nexport { baseConverter } from './others/base-converter';\nexport { decimalToBinary } from './others/base-converter';\nexport { parenthesesChecker } from './others/balanced-symbols';\n\n// chapter 04\nexport { default as Queue } from './data-structures/queue';\nexport { default as Deque } from './data-structures/deque';\nexport { hotPotato } from './others/hot-potato';\nexport { palindromeChecker } from './others/palindrome-checker';\n\n// chapter 05\nexport { default as LinkedList } from './data-structures/linked-list';\nexport { default as DoublyLinkedList } from './data-structures/doubly-linked-list';\nexport { default as CircularLinkedList } from './data-structures/circular-linked-list';\nexport { default as SortedLinkedList } from './data-structures/sorted-linked-list';\nexport { default as StackLinkedList } from './data-structures/stack-linked-list';\n\n// chapter 06\nexport { default as Set } from './data-structures/set';\n\n// chapter 07\nexport { default as Dictionary } from './data-structures/dictionary';\nexport { default as HashTable } from './data-structures/hash-table';\nexport { default as HashTableSeparateChaining } from './data-structures/hash-table-separate-chaining';\nexport { default as HashTableLinearProbing } from './data-structures/hash-table-linear-probing';\nexport { default as HashTableLinearProbingLazy } from './data-structures/hash-table-linear-probing-lazy';\n\n// chapter 08\nexport { default as factorialIterative } from './others/factorial';\nexport { default as factorial } from './others/factorial';\nexport { default as fibonacci } from './others/fibonacci';\nexport { default as fibonacciIterative } from './others/fibonacci';\nexport { default as fibonacciMemoization } from './others/fibonacci';\n\n// chapter 09\nexport { default as BinarySearchTree } from './data-structures/binary-search-tree';\nexport { default as AVLTree } from './data-structures/avl-tree';\n\n// chapter 10\nexport { MinHeap } from './data-structures/heap';\nexport { MaxHeap } from './data-structures/heap';\nexport { default as heapSort } from './algorithms/sorting/heap-sort';\n\n// chapter 11\nexport { default as Graph } from './data-structures/graph';\nexport { breadthFirstSearch } from './algorithms/graph/breadth-first-search';\nexport { BFS } from './algorithms/graph/breadth-first-search';\nexport { depthFirstSearch } from './algorithms/graph/depth-first-search';\nexport { DFS } from './algorithms/graph/depth-first-search';\nexport { dijkstra } from './algorithms/graph/dijkstra';\nexport { floydWarshall } from './algorithms/graph/floyd-warshall';\nexport { prim } from './algorithms/graph/prim';\nexport { kruskal } from './algorithms/graph/kruskal';\n\n// chapter 12\nexport { shuffle } from './algorithms/shuffle/fisher–yates';\n\nexport { bubbleSort } from './algorithms/sorting/bubble-sort';\nexport { modifiedBubbleSort } from './algorithms/sorting/bubble-sort-improved';\nexport { bucketSort } from './algorithms/sorting/bucket-sort';\nexport { countingSort } from './algorithms/sorting/counting-sort';\nexport { insertionSort } from './algorithms/sorting/insertion-sort';\nexport { mergeSort } from './algorithms/sorting/merge-sort';\nexport { quickSort } from './algorithms/sorting/quicksort';\nexport { radixSort } from './algorithms/sorting/radix-sort';\nexport { selectionSort } from './algorithms/sorting/selection-sort';\nexport { shellSort } from './algorithms/sorting/shell-sort';\n\nexport { binarySearch } from './algorithms/search/binary-search';\nexport { interpolationSearch } from './algorithms/search/interpolation-search';\nexport { sequentialSearch } from './algorithms/search/sequential-search';\nexport { findMaxValue } from './algorithms/search/min-max-search';\nexport { findMinValue } from './algorithms/search/min-max-search';\n\n// chapter 14\nexport { binarySearch as binarySearchRecursive } from './algorithms/search/binary-search-recursive';\nexport { minCoinChange } from './algorithms/dynamic-programing/min-coin-change';\nexport { minCoinChange as minCoinChangeGreedy } from './algorithms/greedy/min-coin-change';\nexport { knapSack } from './algorithms/dynamic-programing/knapsack';\nexport { knapSack as knapSackRecursive } from './algorithms/dynamic-programing/knapsack-recursive';\nexport { knapSack as knapSackGreedy } from './algorithms/greedy/knapsack';\nexport { lcs } from './algorithms/dynamic-programing/longest-common-subsequence';\nexport { lcs as lcsPrint } from './algorithms/dynamic-programing/longest-common-subsequence-print';\nexport { lcs as lcsRecursive } from './algorithms/greedy/longest-common-subsequence';\nexport { matrixChainOrder } from './algorithms/dynamic-programing/matrix-chain-multiplication';\nexport { matrixChainOrder as matrixChainOrderGreedy } from './algorithms/greedy/matrix-chain-multiplication';\nexport { ratInAMaze } from './algorithms/backtracking/rat-in-maze';\nexport { sudokuSolver } from './algorithms/backtracking/sudoku-solver';\n"],"sourceRoot":""} \ No newline at end of file diff --git a/chapter01/01-HelloWorld.html b/examples/chapter01_02/01-HelloWorld.html similarity index 100% rename from chapter01/01-HelloWorld.html rename to examples/chapter01_02/01-HelloWorld.html diff --git a/examples/chapter01_02/01-HelloWorld.js b/examples/chapter01_02/01-HelloWorld.js new file mode 100644 index 00000000..b67b0e2c --- /dev/null +++ b/examples/chapter01_02/01-HelloWorld.js @@ -0,0 +1,10 @@ +// @ts-check +/* eslint-disable */ + +function output(t) { + document.write('

' + t + '

'); +} + +alert('Hello, World!'); +console.log('Hello, World!'); +output('Hello, World!'); diff --git a/chapter01/02-Variables.html b/examples/chapter01_02/02-Variables.html similarity index 100% rename from chapter01/02-Variables.html rename to examples/chapter01_02/02-Variables.html diff --git a/examples/chapter01_02/02-Variables.js b/examples/chapter01_02/02-Variables.js new file mode 100644 index 00000000..4d1cf7d5 --- /dev/null +++ b/examples/chapter01_02/02-Variables.js @@ -0,0 +1,40 @@ +// @ts-check +/* eslint-disable */ + +var num = 1; // {1} +num = 3; // {2} + +var price = 1.5; // {3} +var myName = 'Packt'; // {4} +var trueValue = true; // {5} +var nullVar = null; // {6} +var und; // {7} + +console.log('num: ' + num); +console.log('myName: ' + myName); +console.log('trueValue: ' + trueValue); +console.log('price: ' + price); +console.log('nullVar: ' + nullVar); +console.log('und: ' + und); + +// ******* Variable Scope + +var myVariable = 'global'; +myOtherVariable = 'global'; + +function myFunction() { + var myVariable = 'local'; + return myVariable; +} + +function myOtherFunction() { + myOtherVariable = 'local'; + return myOtherVariable; +} + +console.log(myVariable); //{1} +console.log(myFunction()); //{2} + +console.log(myOtherVariable); //{3} +console.log(myOtherFunction()); //{4} +console.log(myOtherVariable); //{5} diff --git a/chapter01/03-Operators.html b/examples/chapter01_02/03-Operators.html similarity index 100% rename from chapter01/03-Operators.html rename to examples/chapter01_02/03-Operators.html diff --git a/chapter01/03-Operators.js b/examples/chapter01_02/03-Operators.js similarity index 58% rename from chapter01/03-Operators.js rename to examples/chapter01_02/03-Operators.js index d1044b92..7895b17b 100755 --- a/chapter01/03-Operators.js +++ b/examples/chapter01_02/03-Operators.js @@ -1,28 +1,25 @@ -/* Arithmetic operators */ -var num = 0; +// @ts-check +/* eslint-disable */ +/* Arithmetic operators */ +var num = 0; // {1} console.log('num value is ' + num); num = num + 2; - console.log('New num value is ' + num); num = num * 3; - console.log('New num value is ' + num); num = num / 2; - console.log('New num value is ' + num); num++; - num--; console.log('New num value is ' + num); -console.log('num mod 2 value is ' + (num % 2)); - +console.log('num mod 2 value is ' + num % 2); /* Assignment operators */ num += 1; @@ -45,24 +42,24 @@ console.log('num <= 1 : ' + (num <= 1)); /* Logical operators */ console.log('true && false : ' + (true && false)); console.log('true || false : ' + (true || false)); -console.log('!true : ' + (!true)); +console.log('!true : ' + !true); /* Bitwise operators */ -console.log('5 & 1:', (5 & 1)); //same as 0101 & 0001 (result 0001 / 1) -console.log('5 | 1:', (5 | 1)); //same as 0101 | 0001 (result 0101 / 5) -console.log('~ 5:', (~5)); //same as ~0101 (result 1010 / 10) -console.log('5 ^ 1:', (5 ^ 1)); //same as 0101 ^ 0001 (result 0100 / 4) -console.log('5 << 1:', (5 << 1)); //same as 0101 << 1 (result 1010 / 10) -console.log('5 >> 1:', (5 >> 1)); //same as 0101 >> 1 (result 0010 / 2) +console.log('5 & 1:', 5 & 1); // same as 0101 & 0001 (result 0001 / 1) +console.log('5 | 1:', 5 | 1); // same as 0101 | 0001 (result 0101 / 5) +console.log('~ 5:', ~5); // same as ~0101 (result 1010 / 10) +console.log('5 ^ 1:', 5 ^ 1); // same as 0101 ^ 0001 (result 0100 / 4) +console.log('5 << 1:', 5 << 1); // same as 0101 << 1 (result 1010 / 10) +console.log('5 >> 1:', 5 >> 1); // same as 0101 >> 1 (result 0010 / 2) /* typeOf */ console.log('typeof num:', typeof num); console.log('typeof Packt:', typeof 'Packt'); console.log('typeof true:', typeof true); -console.log('typeof [1,2,3]:', typeof [1,2,3]); -console.log('typeof {name:John}:', typeof {name:'John'}); +console.log('typeof [1,2,3]:', typeof [1, 2, 3]); +console.log('typeof {name:John}:', typeof { name: 'John' }); /* delete */ -var myObj = {name: 'John', age: 21}; +var myObj = { name: 'John', age: 21 }; delete myObj.age; -console.log(myObj); //Object {name: "John"} \ No newline at end of file +console.log(myObj); // Object {name: "John"} diff --git a/chapter01/04-TruthyFalsy.html b/examples/chapter01_02/04-TruthyFalsy.html similarity index 100% rename from chapter01/04-TruthyFalsy.html rename to examples/chapter01_02/04-TruthyFalsy.html diff --git a/examples/chapter01_02/04-TruthyFalsy.js b/examples/chapter01_02/04-TruthyFalsy.js new file mode 100644 index 00000000..c64fa3e1 --- /dev/null +++ b/examples/chapter01_02/04-TruthyFalsy.js @@ -0,0 +1,27 @@ +// @ts-check +/* eslint-disable */ + +function testTruthy(val) { + return val ? console.log('truthy') : console.log('falsy'); +} + +testTruthy(true); // true +testTruthy(false); // false +testTruthy(new Boolean(false)); // true (object is always true) + +testTruthy(''); // false +testTruthy('a'); // true +testTruthy('Packt'); // true +testTruthy(new String('')); // true (object is always true) + +testTruthy(1); // true +testTruthy(-1); // true +testTruthy(NaN); // false +testTruthy(new Number(NaN)); // true (object is always true) + +testTruthy({}); // true (object is always true) + +var obj = { name: 'John' }; +testTruthy(obj); // true +testTruthy(obj.name); // true +testTruthy(obj.age); // age (property does not exist) diff --git a/chapter01/05-EqualsOperators.html b/examples/chapter01_02/05-EqualsOperators.html similarity index 100% rename from chapter01/05-EqualsOperators.html rename to examples/chapter01_02/05-EqualsOperators.html diff --git a/examples/chapter01_02/05-EqualsOperators.js b/examples/chapter01_02/05-EqualsOperators.js new file mode 100644 index 00000000..d5b43ecc --- /dev/null +++ b/examples/chapter01_02/05-EqualsOperators.js @@ -0,0 +1,39 @@ +// @ts-check +/* eslint-disable */ + +// Packt == true + +console.log('packt' ? true : false); +// outputs true + +console.log('packt' == true); +// 1 - converts Boolean using toNumber +// 'packt' == 1 +// 2 - converts String using toNumber +// NaN == 1 +// outputs false + +console.log('packt' == false); +// 1 - converts Boolean using toNumber +// 'packt' == 0 +// 2 - converts String using toNumber +// NaN == 0 +// outputs false + +console.log([0] == true); +// 1 - converts Boolean using toNumber +// [0] == 1 +// 2 - converts Object using toPrimitive +// 2.1 - [0].valueOf() is not primitive +// 2.2 - [0].toString is 0 +// 0 == 1 +// outputs false + +//* ****************************** === +console.log('packt' === true); // false + +console.log('packt' === 'packt'); // true + +var person1 = { name: 'John' }; +var person2 = { name: 'John' }; +console.log(person1 === person2); // false, different objects diff --git a/chapter01/06-ConditionalStatements.html b/examples/chapter01_02/06-ConditionalStatements.html similarity index 100% rename from chapter01/06-ConditionalStatements.html rename to examples/chapter01_02/06-ConditionalStatements.html diff --git a/examples/chapter01_02/06-ConditionalStatements.js b/examples/chapter01_02/06-ConditionalStatements.js new file mode 100644 index 00000000..c939967c --- /dev/null +++ b/examples/chapter01_02/06-ConditionalStatements.js @@ -0,0 +1,54 @@ +// @ts-check +/* eslint-disable */ + +/* Example 01 - if */ +var num = 1; +if (num === 1) { + console.log('num is equal to 1'); +} + +/* Example 02 - if-else */ +var num = 0; +if (num === 1) { + console.log('num is equal to 1'); +} else { + console.log('num is not equal to 1, the value of num is ' + num); +} + +/* Example 03 - if-else-if-else... */ +var month = 5; +if (month === 1) { + console.log('January'); +} else if (month === 2) { + console.log('February'); +} else if (month === 3) { + console.log('March'); +} else { + console.log('Month is not January, February or March'); +} + +/* Example 04 - switch */ +var month = 5; +switch (month) { + case 1: + console.log('January'); + break; + case 2: + console.log('February'); + break; + case 3: + console.log('March'); + break; + default: + console.log('Month is not January, February or March'); +} + +/* Example 05 - ternary operator - if..else */ +if (num === 1) { + num--; +} else { + num++; +} + +// is the same as +num === 1 ? num-- : num++; diff --git a/chapter01/07-Loops.html b/examples/chapter01_02/07-Loops.html similarity index 100% rename from chapter01/07-Loops.html rename to examples/chapter01_02/07-Loops.html diff --git a/chapter01/07-Loops.js b/examples/chapter01_02/07-Loops.js similarity index 56% rename from chapter01/07-Loops.js rename to examples/chapter01_02/07-Loops.js index 61cf20cb..9d12b19e 100755 --- a/chapter01/07-Loops.js +++ b/examples/chapter01_02/07-Loops.js @@ -1,23 +1,24 @@ -console.log('**** for example ****'); +// @ts-check +/* eslint-disable */ +console.log('**** for example ****'); /* for - example */ -for (var i=0; i<10; i++) { - console.log(i); +for (var i = 0; i < 10; i++) { + console.log(i); } console.log('**** while example ****'); /* while - example */ var i = 0; -while(i<10) -{ - console.log(i); - i++; +while (i < 10) { + console.log(i); + i++; } console.log('**** do-while example ****'); /* do-while - example */ var i = 0; do { - console.log(i); - i++; -} while (i<10) \ No newline at end of file + console.log(i); + i++; +} while (i < 10); diff --git a/chapter01/08-Functions.html b/examples/chapter01_02/08-Functions.html similarity index 100% rename from chapter01/08-Functions.html rename to examples/chapter01_02/08-Functions.html diff --git a/chapter01/08-Functions.js b/examples/chapter01_02/08-Functions.js similarity index 66% rename from chapter01/08-Functions.js rename to examples/chapter01_02/08-Functions.js index 9915e566..52d5f9c8 100644 --- a/chapter01/08-Functions.js +++ b/examples/chapter01_02/08-Functions.js @@ -1,12 +1,15 @@ +// @ts-check +/* eslint-disable */ + function sayHello() { - console.log('Hello!'); + console.log('Hello!'); } sayHello(); /* function with parameter */ function output(text) { - console.log(text); + console.log(text); } output('Hello!'); @@ -17,13 +20,8 @@ output(); /* function using the return statement */ function sum(num1, num2) { - return num1 + num2; + return num1 + num2; } -var result = sum(1,2); +var result = sum(1, 2); output(result); - - - - - diff --git a/chapter01/10-ObjectOrientedJS.html b/examples/chapter01_02/09-ObjectOrientedJS.html similarity index 59% rename from chapter01/10-ObjectOrientedJS.html rename to examples/chapter01_02/09-ObjectOrientedJS.html index 1b3848bd..cfbe1a04 100644 --- a/chapter01/10-ObjectOrientedJS.html +++ b/examples/chapter01_02/09-ObjectOrientedJS.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter01_02/09-ObjectOrientedJS.js b/examples/chapter01_02/09-ObjectOrientedJS.js new file mode 100644 index 00000000..28c15a1c --- /dev/null +++ b/examples/chapter01_02/09-ObjectOrientedJS.js @@ -0,0 +1,42 @@ +// @ts-check +/* eslint-disable */ + +/* Object example 1 */ +var obj = new Object(); + +/* Object example 2 */ +var obj = {}; + +obj = { + name: { + first: 'Gandalf', + last: 'the Grey' + }, + address: 'Middle Earth' +}; + +/* Object example 3 */ +function Book(title, pages, isbn) { + this.title = title; + this.pages = pages; + this.isbn = isbn; + this.printIsbn = function() { + console.log(this.isbn); + }; +} + +var book = new Book('title', 'pag', 'isbn'); + +console.log(book.title); // outputs the book title + +book.title = 'new title'; // update the value of the book title + +console.log(book.title); // outputs the updated value + +Book.prototype.printTitle = function() { + console.log(this.title); +}; + +book.printTitle(); + +book.printIsbn(); diff --git a/chapter01/13-ES6ArrowFunctions.html b/examples/chapter01_02/10-ES2015-ES6-letconst.html similarity index 57% rename from chapter01/13-ES6ArrowFunctions.html rename to examples/chapter01_02/10-ES2015-ES6-letconst.html index 1d085ec4..ba8c81d0 100644 --- a/chapter01/13-ES6ArrowFunctions.html +++ b/examples/chapter01_02/10-ES2015-ES6-letconst.html @@ -5,7 +5,7 @@ - + - \ No newline at end of file + diff --git a/examples/chapter01_02/10-ES2015-ES6-letconst.js b/examples/chapter01_02/10-ES2015-ES6-letconst.js new file mode 100644 index 00000000..0295e187 --- /dev/null +++ b/examples/chapter01_02/10-ES2015-ES6-letconst.js @@ -0,0 +1,31 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): let and const keywords + +//* ****** EcmaScript 2015 (ES6): let is the new var (https://goo.gl/he0udZ) +var framework = 'Angular'; +var framework = 'React'; +console.log(framework); + +let language = 'JavaScript!'; // {1} +// let language = 'Ruby!'; // {2} - throws error +console.log(language); + + +//* ****** EcmaScript 2015 (ES6): const (https://goo.gl/YUQj3r) +const PI = 3.141593; +// PI = 3.0; //throws error +console.log(PI); + +const jsFramework = { + name: 'Angular' +}; +jsFramework.name = 'React'; + +// error, cannot reassign object reference +/* +jsFramework = { + name: 'Vue' +}; +*/ diff --git a/examples/chapter01_02/11-ES2015-ES6-variableScope.html b/examples/chapter01_02/11-ES2015-ES6-variableScope.html new file mode 100644 index 00000000..b4d3476f --- /dev/null +++ b/examples/chapter01_02/11-ES2015-ES6-variableScope.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter01_02/11-ES2015-ES6-variableScope.html.js b/examples/chapter01_02/11-ES2015-ES6-variableScope.html.js new file mode 100644 index 00000000..3f5f022a --- /dev/null +++ b/examples/chapter01_02/11-ES2015-ES6-variableScope.html.js @@ -0,0 +1,46 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): variables scope (https://goo.gl/NbsVvg) +let movie = 'Lord of the Rings'; // {1} +// var movie = 'Batman v Superman'; //throws error, variable movie already declared + +function starWarsFan() { + const movie = 'Star Wars'; // {2} + return movie; +} + +function marvelFan() { + movie = 'The Avengers'; // {3} + return movie; +} + +function blizzardFan() { + const isFan = true; + let phrase = 'Warcraft'; // {4} + console.log('Before if: ' + phrase); + if (isFan) { + let phrase = 'initial text'; // {5} + phrase = 'For the Horde!'; // {6} + console.log('Inside if: ' + phrase); + } + phrase = 'For the Alliance!'; // {7} + console.log('After if: ' + phrase); +} + +console.log(movie); // {8} +console.log(starWarsFan()); // {9} +console.log(marvelFan()); // {10} +console.log(movie); // {11} +blizzardFan(); // {12} + +// output +// Lord of the Rings +// Star Wars +// The Avengers +// The Avengers +// Before if: Warcraft +// Inside if: For the Horde! +// After if: For the Alliance! + + diff --git a/chapter01/15-ES6EnhancedObjectProperties.html b/examples/chapter01_02/12-ES2015-ES6-StringTemplates.html similarity index 55% rename from chapter01/15-ES6EnhancedObjectProperties.html rename to examples/chapter01_02/12-ES2015-ES6-StringTemplates.html index 3e040b16..c7eb7ef3 100644 --- a/chapter01/15-ES6EnhancedObjectProperties.html +++ b/examples/chapter01_02/12-ES2015-ES6-StringTemplates.html @@ -5,7 +5,7 @@ - + - \ No newline at end of file + diff --git a/examples/chapter01_02/12-ES2015-ES6-StringTemplates.js b/examples/chapter01_02/12-ES2015-ES6-StringTemplates.js new file mode 100644 index 00000000..b1a65b40 --- /dev/null +++ b/examples/chapter01_02/12-ES2015-ES6-StringTemplates.js @@ -0,0 +1,14 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): Template literals (https://goo.gl/4N36CS) +const book = { + name: 'Learning JavaScript DataStructures and Algorithms' +}; + +console.log('You are reading ' + book.name + '.,\n and this is a new line\n and so is this.'); + +console.log(`You are reading ${book.name}., + and this is a new line + and so is this.`); + diff --git a/examples/chapter01_02/13-ES2015-ES6-ArrowFunctions.html b/examples/chapter01_02/13-ES2015-ES6-ArrowFunctions.html new file mode 100644 index 00000000..0a922d1c --- /dev/null +++ b/examples/chapter01_02/13-ES2015-ES6-ArrowFunctions.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter01_02/13-ES2015-ES6-ArrowFunctions.js b/examples/chapter01_02/13-ES2015-ES6-ArrowFunctions.js new file mode 100644 index 00000000..8f4775f3 --- /dev/null +++ b/examples/chapter01_02/13-ES2015-ES6-ArrowFunctions.js @@ -0,0 +1,23 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): arrow functions (https://goo.gl/nM414v) +var circleAreaES5 = function circleArea(r) { + var PI = 3.14; + var area = PI * r * r; + return area; +}; +console.log(circleAreaES5(2)); + +const circleArea = r => { // {1} + const PI = 3.14; + const area = PI * r * r; + return area; +}; +console.log(circleArea(2)); + +const circleArea2 = r => 3.14 * r * r; +console.log(circleArea2(2)); + +const hello = () => console.log('hello!'); +hello(); diff --git a/chapter01/14-ES6ParameterHandling.html b/examples/chapter01_02/14-ES2015-ES6-ParameterHandling.html similarity index 55% rename from chapter01/14-ES6ParameterHandling.html rename to examples/chapter01_02/14-ES2015-ES6-ParameterHandling.html index 1d220b1b..703cf2c9 100644 --- a/chapter01/14-ES6ParameterHandling.html +++ b/examples/chapter01_02/14-ES2015-ES6-ParameterHandling.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter01_02/14-ES2015-ES6-ParameterHandling.js b/examples/chapter01_02/14-ES2015-ES6-ParameterHandling.js new file mode 100644 index 00000000..66a6e089 --- /dev/null +++ b/examples/chapter01_02/14-ES2015-ES6-ParameterHandling.js @@ -0,0 +1,48 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): Default Parameter Values (https://goo.gl/AP5EYb) +function sum(x = 1, y = 2, z = 3) { + return x + y + z; +} +console.log(sum(4, 2)); // outputs 9 + +// function above is the same as +function sum2(x, y, z) { + if (x === undefined) x = 1; + if (y === undefined) y = 2; + if (z === undefined) z = 3; + return x + y + z; +} +console.log(sum2(4, 2)); // outputs 9 + +// or +function sum3() { + var x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2; + var z = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 3; + + return x + y + z; +} +console.log(sum3(4, 2)); // outputs 9 + +//* ****** EcmaScript 6: spread operator ('...') (https://goo.gl/8equk5) +let params = [3, 4, 5]; +console.log(sum(...params)); // ES2015 +console.log(sum.apply(undefined, params)); // ES5 + +let numbers = [1, 2, ...params]; // pushing values into array +console.log(numbers); + +//* ****** EcmaScript 6: rest parameter ('...') (https://goo.gl/LaJZqU) +function restParamaterFunction(x, y, ...a) { + return (x + y) * a.length; +} +console.log(restParamaterFunction(1, 2, 'hello', true, 7)); // outputs 9; + +// code above is the same as ES5: +function restParamaterFunction2(x, y) { + var a = Array.prototype.slice.call(arguments, 2); + return (x + y) * a.length; +} +console.log(restParamaterFunction2(1, 2, 'hello', true, 7)); diff --git a/examples/chapter01_02/15-ES2015-ES6-EnhancedObjectProperties.html b/examples/chapter01_02/15-ES2015-ES6-EnhancedObjectProperties.html new file mode 100644 index 00000000..c915b7d8 --- /dev/null +++ b/examples/chapter01_02/15-ES2015-ES6-EnhancedObjectProperties.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter01_02/15-ES2015-ES6-EnhancedObjectProperties.js b/examples/chapter01_02/15-ES2015-ES6-EnhancedObjectProperties.js new file mode 100644 index 00000000..00ec03ad --- /dev/null +++ b/examples/chapter01_02/15-ES2015-ES6-EnhancedObjectProperties.js @@ -0,0 +1,37 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): Destructuring Assignment + Property Shorthand (https://goo.gl/VsLecp ) +let [x, y] = ['a', 'b']; +let obj = { x, y }; +console.log(obj); // { x: "a", y: "b" } + +// swap (https://goo.gl/EyFAII) +[x, y] = [y, x]; +var temp = x; +x = y; +y = temp; + +// code above is the same as +var x2 = 'a'; +var y2 = 'b'; +var obj2 = { x2: x2, y2: y2 }; +console.log(obj2); // { x: "a", y: "b" } + +// Method Properties (https://goo.gl/DKU2PN) +const hello = { + name: 'abcdef', + printHello() { + console.log('Hello'); + } +}; +console.log(hello.printHello()); + +// code above is the same as: +var hello2 = { + name: 'abcdef', + printHello: function printHello() { + console.log('Hello'); + } +}; +console.log(hello2.printHello()); diff --git a/chapter01/12-Es6StringTemplates.html b/examples/chapter01_02/16-ES2015-ES6-Classes.html similarity index 62% rename from chapter01/12-Es6StringTemplates.html rename to examples/chapter01_02/16-ES2015-ES6-Classes.html index 3d730209..95f0d6d5 100644 --- a/chapter01/12-Es6StringTemplates.html +++ b/examples/chapter01_02/16-ES2015-ES6-Classes.html @@ -5,7 +5,6 @@ - - + - \ No newline at end of file + diff --git a/examples/chapter01_02/16-ES2015-ES6-Classes.js b/examples/chapter01_02/16-ES2015-ES6-Classes.js new file mode 100644 index 00000000..c088b6bb --- /dev/null +++ b/examples/chapter01_02/16-ES2015-ES6-Classes.js @@ -0,0 +1,89 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2015 (ES6): classes (https://goo.gl/UhK1n4) +class Book { + constructor(title, pages, isbn) { + this.title = title; + this.pages = pages; + this.isbn = isbn; + } + printIsbn() { + console.log(this.isbn); + } +} + +let book = new Book('title', 'pag', 'isbn'); + +console.log(book.title); // outputs the book title + +book.title = 'new title'; // update the value of the book title + +console.log(book.title); // outputs the book title + +// inheritance (https://goo.gl/hgQvo9) +class ITBook extends Book { // {1} + constructor(title, pages, isbn, technology) { + super(title, pages, isbn); // {2} + this.technology = technology; + } + + printTechnology() { + console.log(this.technology); + } +} + +let jsBook = new ITBook( + 'Learning JS Algorithms', + '200', + '1234567890', + 'JavaScript' +); + +console.log(jsBook.title); +console.log(jsBook.printTechnology()); + +// getter and setters (https://goo.gl/SMRYsv) +class Person { + constructor(name) { + this._name = name; // {1} + } + + get name() { // {2} + return this._name; + } + + set name(value) { // {3} + this._name = value; + } +} + +let lotrChar = new Person('Frodo'); +console.log(lotrChar.name); // {4} +lotrChar.name = 'Gandalf'; // {5} +console.log(lotrChar.name); +lotrChar._name = 'Sam'; // {6} +console.log(lotrChar.name); + +// using symbols for private atributes +var _name = Symbol(); +class Person2 { + constructor(name) { + this[_name] = name; + } + + get name() { + return this[_name]; + } + + set name(value) { + this[_name] = value; + } +} + +let lotrChar2 = new Person2('Frodo'); +console.log(lotrChar2.name); +lotrChar2.name = 'Gandalf'; +console.log(lotrChar2.name); + +console.log(Object.getOwnPropertySymbols(lotrChar2)); diff --git a/examples/chapter01_02/17-Book.js b/examples/chapter01_02/17-Book.js new file mode 100644 index 00000000..8b8b4f48 --- /dev/null +++ b/examples/chapter01_02/17-Book.js @@ -0,0 +1,11 @@ +// @ts-check +/* eslint-disable */ + +export default class Book { + constructor(title) { + this.title = title; + } + printTitle() { + console.log(this.title); + } +} diff --git a/examples/chapter01_02/17-CalcArea.js b/examples/chapter01_02/17-CalcArea.js new file mode 100644 index 00000000..085e9ef0 --- /dev/null +++ b/examples/chapter01_02/17-CalcArea.js @@ -0,0 +1,9 @@ +// @ts-check +/* eslint-disable */ + +export const circleArea = r => 3.14 * (r ** 2); + +export const squareArea = s => s * s; + +// export { circleArea, squareArea }; // {1} +export { circleArea as circle, squareArea as square }; diff --git a/examples/chapter01_02/17-ES2015-ES6-Modules-node.js b/examples/chapter01_02/17-ES2015-ES6-Modules-node.js new file mode 100644 index 00000000..7512f4ca --- /dev/null +++ b/examples/chapter01_02/17-ES2015-ES6-Modules-node.js @@ -0,0 +1,11 @@ +// @ts-check +/* eslint-disable */ + +const area = require('./lib/17-CalcArea'); +const Book = require('./lib/17-Book'); + +console.log(area.circle(2)); +console.log(area.square(2)); + +const myBook = new Book('some title'); +myBook.printTitle(); diff --git a/examples/chapter01_02/17-ES2015-ES6-Modules.html b/examples/chapter01_02/17-ES2015-ES6-Modules.html new file mode 100644 index 00000000..fb2709ae --- /dev/null +++ b/examples/chapter01_02/17-ES2015-ES6-Modules.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter01_02/17-ES2015-ES6-Modules.js b/examples/chapter01_02/17-ES2015-ES6-Modules.js new file mode 100644 index 00000000..da26b541 --- /dev/null +++ b/examples/chapter01_02/17-ES2015-ES6-Modules.js @@ -0,0 +1,20 @@ +// @ts-check +/* eslint-disable */ +// import { circleArea, squareArea } from './17-CalcArea'; // {2} +// import { circleArea as circle } from './17-CalcArea'; + +// console.log(circleArea(2)); +// console.log(squareArea(2)); + +/* Different way of importing the module */ +// import * as area from './17-CalcArea'; +// import Book from './17-Book'; + +import * as area from './17-CalcArea.js'; // we need the .js to run this code in the browser +import Book from './17-Book.js'; + +console.log(area.circle(2)); +console.log(area.square(2)); + +const myBook = new Book('some title'); +myBook.printTitle(); diff --git a/examples/chapter01_02/17-ES2015-Modules-node/17-Book.mjs b/examples/chapter01_02/17-ES2015-Modules-node/17-Book.mjs new file mode 100644 index 00000000..076f2bb0 --- /dev/null +++ b/examples/chapter01_02/17-ES2015-Modules-node/17-Book.mjs @@ -0,0 +1,8 @@ +export default class Book { + constructor(title) { + this.title = title; + } + printTitle() { + console.log(this.title); + } +} diff --git a/examples/chapter01_02/17-ES2015-Modules-node/17-CalcArea.mjs b/examples/chapter01_02/17-ES2015-Modules-node/17-CalcArea.mjs new file mode 100644 index 00000000..ca4454a5 --- /dev/null +++ b/examples/chapter01_02/17-ES2015-Modules-node/17-CalcArea.mjs @@ -0,0 +1,6 @@ +export const circleArea = r => 3.14 * (r ** 2); + +export const squareArea = s => s * s; + +// export { circleArea, squareArea }; // {1} +export { circleArea as circle, squareArea as square }; diff --git a/examples/chapter01_02/17-ES2015-Modules-node/17-ES2015-ES6-Modules.mjs b/examples/chapter01_02/17-ES2015-Modules-node/17-ES2015-ES6-Modules.mjs new file mode 100644 index 00000000..53817060 --- /dev/null +++ b/examples/chapter01_02/17-ES2015-Modules-node/17-ES2015-ES6-Modules.mjs @@ -0,0 +1,8 @@ +import * as area from './17-CalcArea.mjs'; +import Book from './17-Book.mjs'; + +console.log(area.circle(2)); +console.log(area.square(2)); + +const myBook = new Book('some title'); +myBook.printTitle(); diff --git a/examples/chapter01_02/18-ES2016-ES7-ExponentiationOperator.html b/examples/chapter01_02/18-ES2016-ES7-ExponentiationOperator.html new file mode 100644 index 00000000..129d0193 --- /dev/null +++ b/examples/chapter01_02/18-ES2016-ES7-ExponentiationOperator.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/chapter01_02/18-ES2016-ES7-ExponentiationOperator.js b/examples/chapter01_02/18-ES2016-ES7-ExponentiationOperator.js new file mode 100644 index 00000000..705933de --- /dev/null +++ b/examples/chapter01_02/18-ES2016-ES7-ExponentiationOperator.js @@ -0,0 +1,12 @@ +// @ts-check +/* eslint-disable */ + +//* ****** EcmaScript 2016 (ES7): Exponentiation operator (https://goo.gl/Z6dCFB) +let r = 2; +const area = 3.14 * r * r; +const area2 = 3.14 * Math.pow(r, 2); +const area3 = 3.14 * r ** 2; + +console.log(area); +console.log(area2); +console.log(area3); diff --git a/examples/chapter01_02/lib/17-Book.js b/examples/chapter01_02/lib/17-Book.js new file mode 100644 index 00000000..802d4191 --- /dev/null +++ b/examples/chapter01_02/lib/17-Book.js @@ -0,0 +1,63 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["module", "exports"], factory); + } else if (typeof exports !== "undefined") { + factory(module, exports); + } else { + var mod = { + exports: {} + }; + factory(mod, mod.exports); + global.Book = mod.exports; + } +})(this, function (module, exports) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + var _createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + var Book = function () { + function Book(title) { + _classCallCheck(this, Book); + + this.title = title; + } + + _createClass(Book, [{ + key: "printTitle", + value: function printTitle() { + console.log(this.title); + } + }]); + + return Book; + }(); + + exports.default = Book; + module.exports = exports["default"]; +}); \ No newline at end of file diff --git a/examples/chapter01_02/lib/17-CalcArea.js b/examples/chapter01_02/lib/17-CalcArea.js new file mode 100644 index 00000000..63335f1d --- /dev/null +++ b/examples/chapter01_02/lib/17-CalcArea.js @@ -0,0 +1,30 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports"], factory); + } else if (typeof exports !== "undefined") { + factory(exports); + } else { + var mod = { + exports: {} + }; + factory(mod.exports); + global.CalcArea = mod.exports; + } +})(this, function (exports) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var circleArea = exports.circleArea = function circleArea(r) { + return 3.14 * Math.pow(r, 2); + }; + + var squareArea = exports.squareArea = function squareArea(s) { + return s * s; + }; + + // export { circleArea, squareArea }; // {1} + exports.circle = circleArea; + exports.square = squareArea; +}); \ No newline at end of file diff --git a/examples/chapter01_02/lib/17-ES2015-ES6-Modules-bundle.js b/examples/chapter01_02/lib/17-ES2015-ES6-Modules-bundle.js new file mode 100644 index 00000000..bc101140 --- /dev/null +++ b/examples/chapter01_02/lib/17-ES2015-ES6-Modules-bundle.js @@ -0,0 +1,158 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o b.age ? 1 : -1; + }; + return MyObject; +}()); +function compareTwoObjects(a, b) { + console.log(a.compareTo(b)); + console.log(b.compareTo(a)); +} diff --git a/examples/chapter01_02/typescript/hello-world.ts b/examples/chapter01_02/typescript/hello-world.ts new file mode 100644 index 00000000..7cb7ace8 --- /dev/null +++ b/examples/chapter01_02/typescript/hello-world.ts @@ -0,0 +1,46 @@ +let myName = 'Packt'; +// myName = 10; + +let age = 20; // number +let existsFlag = true; // boolean +let language = 'JavaScript'; // string + +let favoriteLanguage: string; +let langs = ['JavaScript', 'Ruby', 'Python']; +favoriteLanguage = langs[0]; + +interface Person { + name: string; + age: number; +} + +function printName(person: Person) { + console.log(person.name); +} + +const john = { name: 'John', age: 21 }; +const mary = { name: 'Mary', age: 21, phone: '123-45678' }; +printName(john); +printName(mary); + +interface Comparable { + compareTo(b: T): number; +} + +class MyObject implements Comparable { + age: number; + + compareTo(b: MyObject): number { + if (this.age === b.age) { + return 0; + } + return this.age > b.age ? 1 : -1; + } +} + +function compareTwoObjects(a: MyObject, b: MyObject) { + console.log(a.compareTo(b)); + console.log(b.compareTo(a)); +} + + diff --git a/chapter02/01-Introduction.html b/examples/chapter03/01-Introduction.html similarity index 100% rename from chapter02/01-Introduction.html rename to examples/chapter03/01-Introduction.html diff --git a/examples/chapter03/01-Introduction.js b/examples/chapter03/01-Introduction.js new file mode 100755 index 00000000..59311202 --- /dev/null +++ b/examples/chapter03/01-Introduction.js @@ -0,0 +1,26 @@ +// @ts-check + +const averageTempJan = 31.9; +const averageTempFeb = 35.3; +const averageTempMar = 42.4; +const averageTempApr = 52; +const averageTempMay = 60.8; + +const averageTemp = []; +averageTemp[0] = 31.9; +averageTemp[1] = 35.3; +averageTemp[2] = 42.4; +averageTemp[3] = 52; +averageTemp[4] = 60.8; + +console.log('averageTempJan', averageTempJan); +console.log('averageTempFeb', averageTempFeb); +console.log('averageTempMar', averageTempMar); +console.log('averageTempApr', averageTempApr); +console.log('averageTempMay', averageTempMay); + +console.log('averageTemp[0]', averageTemp[0]); +console.log('averageTemp[1]', averageTemp[1]); +console.log('averageTemp[2]', averageTemp[2]); +console.log('averageTemp[3]', averageTemp[3]); +console.log('averageTemp[4]', averageTemp[4]); diff --git a/chapter02/02-CreatingAndInitialingArrays.html b/examples/chapter03/02-CreatingAndInitialingArrays.html similarity index 100% rename from chapter02/02-CreatingAndInitialingArrays.html rename to examples/chapter03/02-CreatingAndInitialingArrays.html diff --git a/examples/chapter03/02-CreatingAndInitialingArrays.js b/examples/chapter03/02-CreatingAndInitialingArrays.js new file mode 100755 index 00000000..b07aaed3 --- /dev/null +++ b/examples/chapter03/02-CreatingAndInitialingArrays.js @@ -0,0 +1,36 @@ +// @ts-check +/* eslint-disable */ + +let daysOfWeek = new Array(); // {1} + +daysOfWeek = new Array(7); // {2} + +daysOfWeek = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'); // {3} + +// preferred +daysOfWeek = []; + +daysOfWeek = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; // {3} + +console.log('daysOfWeek.length', daysOfWeek.length); + +for (let i = 0; i < daysOfWeek.length; i++) { + console.log(`daysOfWeek[${i}]`, daysOfWeek[i]); +} + +// fibonacci numbers +// 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ... +const fibonacci = []; // {1} +fibonacci[1] = 1; // {2} +fibonacci[2] = 1; // {3} + +for (let i = 3; i < 20; i++) { + fibonacci[i] = fibonacci[i - 1] + fibonacci[i - 2]; // //{4} +} + +for (let i = 1; i < fibonacci.length; i++) { // {5} + console.log(`fibonacci[${i}]`, fibonacci[i]); // {6} +} + +// instead of {5} and {6} we can simply use +console.log('fibonacci', fibonacci); diff --git a/chapter02/03-AddingRemovingElements.html b/examples/chapter03/03-AddingRemovingElements.html similarity index 100% rename from chapter02/03-AddingRemovingElements.html rename to examples/chapter03/03-AddingRemovingElements.html diff --git a/examples/chapter03/03-AddingRemovingElements.js b/examples/chapter03/03-AddingRemovingElements.js new file mode 100755 index 00000000..9a12e833 --- /dev/null +++ b/examples/chapter03/03-AddingRemovingElements.js @@ -0,0 +1,105 @@ +// @ts-check +/* eslint-disable */ + +function logArray(message = '', array) { + const output = `${message} => (${array.length}) [${array.join(', ')}]`; + document.writeln(`

${output}

`); + console.log(message, array); +} + +let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; + +console.log('Original array', numbers); + +function printArray(myArray) { + for (let i = 0; i < myArray.length; i++) { + console.log(myArray[i]); + } +} + +/****************************** Inserting an element in the end of the Array */ + +// add a new element to the numbers array +numbers[numbers.length] = 10; +console.log('Add 10 to the end', numbers); + +numbers.push(11); +console.log('Add 11 with push', numbers); + +numbers.push(12, 13); +console.log('Add 12 and 13 with push', numbers); + + +// insert first position manually +Array.prototype.insertFirstPosition = function(value) { + for (let i = this.length; i >= 0; i--) { + this[i] = this[i - 1]; + } + this[0] = value; +}; + +numbers.insertFirstPosition(-1); +console.log('Add -1 with insertFirstPosition', numbers); +// printArray(numbers); + +// using method unshift +numbers.unshift(-2); +console.log('Add -2 with unshift', numbers); +//printArray(numbers); + +numbers.unshift(-4, -3); +console.log('Add -4 and -3 with unshift', numbers); +// printArray(numbers); + +// ************** Removing elements + +numbers.pop(); +console.log('Removed last value with pop', numbers); + +for (let i = 0; i < numbers.length; i++) { + numbers[i] = numbers[i + 1]; +} + +console.log('Removed first value manually', numbers); +console.log('Lenght after value removed manually', numbers.length); + +//reset array +numbers = [-4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + +Array.prototype.reIndex = function(myArray) { + const newArray = []; + for(let i = 0; i < myArray.length; i++ ) { + if (myArray[i] !== undefined) { + // console.log(myArray[i]); + newArray.push(myArray[i]); + } + } + return newArray; +} + +// remove first position manually and reIndex +Array.prototype.removeFirstPosition = function() { + for (let i = 0; i < this.length; i++) { + this[i] = this[i + 1]; + } + return this.reIndex(this); +}; + +numbers = numbers.removeFirstPosition(); +console.log('Removed first with removeFirstPosition + reIndex', numbers); + +// using method shift +numbers.shift(); +console.log('Removed first with shift', numbers); +console.log('Lenght after removed first with shift', numbers.length); + +//* *** Removing and Adding elements from the middle of the array or specific position +// splice method - parameter (index, howManyPositionsToBeRemoved, item1...itemX) +numbers.splice(5, 3); +console.log('Removing 3 elements (3, 4, 5) starting index 5', numbers); + +numbers.splice(5, 0, 2, 3, 4); +console.log('Adding 3 elements (2, 3, 4) starting index 5', numbers); + +numbers.splice(5, 3, 2, 3, 4); +console.log('Removing 3 elements starting index 5 and adding (2, 3, 4)', numbers); diff --git a/chapter02/04-TwoDimensionalMultiDimensional.html b/examples/chapter03/04-TwoDimensionalMultiDimensional.html similarity index 100% rename from chapter02/04-TwoDimensionalMultiDimensional.html rename to examples/chapter03/04-TwoDimensionalMultiDimensional.html diff --git a/examples/chapter03/04-TwoDimensionalMultiDimensional.js b/examples/chapter03/04-TwoDimensionalMultiDimensional.js new file mode 100755 index 00000000..97dfb941 --- /dev/null +++ b/examples/chapter03/04-TwoDimensionalMultiDimensional.js @@ -0,0 +1,78 @@ +// @ts-check +/* eslint-disable */ + +let averageTempDay1 = [72, 75, 79, 79, 81, 81]; +let averageTempDay2 = [81, 79, 75, 75, 73, 72]; + +let averageTemp = []; + +// same as +averageTemp[0] = [72, 75, 79, 79, 81, 81]; +averageTemp[1] = [81, 79, 75, 75, 73, 73]; + +function printMatrix(myMatrix) { + for (let i = 0; i < myMatrix.length; i++) { + for (let j = 0; j < myMatrix[i].length; j++) { + console.log(myMatrix[i][j]); + } + } +} + +// printMatrix(averageTemp); +console.log('averageTemp two-dimensional array:'); + +// same as + +// day 1 +averageTemp[0] = []; +averageTemp[0][0] = 72; +averageTemp[0][1] = 75; +averageTemp[0][2] = 79; +averageTemp[0][3] = 79; +averageTemp[0][4] = 81; +averageTemp[0][5] = 81; +// day 2 +averageTemp[1] = []; +averageTemp[1][0] = 81; +averageTemp[1][1] = 79; +averageTemp[1][2] = 75; +averageTemp[1][3] = 75; +averageTemp[1][4] = 73; +averageTemp[1][5] = 73; + +// printMatrix(averageTemp); +console.table(averageTemp); + +//* * Multidimensional Matrix + +// Matrix 3x3x3 - Cube + +const matrix3x3x3 = []; +for (let i = 0; i < 3; i++) { + matrix3x3x3[i] = []; + for (let j = 0; j < 3; j++) { + matrix3x3x3[i][j] = []; + for (let z = 0; z < 3; z++) { + matrix3x3x3[i][j][z] = i + j + z; + } + } +} + +for (let i = 0; i < matrix3x3x3.length; i++) { + for (let j = 0; j < matrix3x3x3[i].length; j++) { + for (let z = 0; z < matrix3x3x3[i][j].length; z++) { + console.log(matrix3x3x3[i][j][z]); + } + } +} + +// user-friendly-output +const matrix3x3x3Output = []; +for (let i = 0; i < 3; i++) { + matrix3x3x3Output[i] = []; + for (let j = 0; j < 3; j++) { + matrix3x3x3Output[i][j] = `[${matrix3x3x3[i][j].join(', ')}]`; + } +} +console.log('matrix3x3x3 three-dimensional array:'); +console.table(matrix3x3x3Output); diff --git a/chapter02/05-ArrayMethods.html b/examples/chapter03/05-ArrayMethods.html similarity index 100% rename from chapter02/05-ArrayMethods.html rename to examples/chapter03/05-ArrayMethods.html diff --git a/examples/chapter03/05-ArrayMethods.js b/examples/chapter03/05-ArrayMethods.js new file mode 100755 index 00000000..67d97602 --- /dev/null +++ b/examples/chapter03/05-ArrayMethods.js @@ -0,0 +1,47 @@ +// @ts-check + +//* ************** Joining multiple arrays +const zero = 0; +const positiveNumbers = [1, 2, 3]; +const negativeNumbers = [-3, -2, -1]; +let numbers = negativeNumbers.concat(zero, positiveNumbers); + +console.log('zero', zero); +console.log('positiveNumbers', positiveNumbers); +console.log('negativeNumbers', negativeNumbers); +console.log('negativeNumbers.concat(zero, positiveNumbers)', numbers); + +/* function isEven(x) { + // returns true if x is a multiple of 2. + console.log(x); + return x % 2 === 0 ? true : false; +} */ // ES5 syntax +const isEven = x => x % 2 === 0; + +numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; +console.log('numbers', numbers); + +// it is going to execute the function only once +console.log('numbers.every(isEven)', numbers.every(isEven)); + +// is going to execute the function twice +console.log('numbers.some(isEven)', numbers.some(isEven)); + +/* numbers.forEach(function(x) { + console.log(x % 2 == 0); +}); */ // ES5 sintax for function below + +numbers.forEach(x => console.log(`numbers.forEach: ${x} % 2 === 0`, x % 2 === 0)); + + +console.log('numbers.map(isEven)', numbers.map(isEven)); + +console.log('numbers.filter(isEven)', numbers.filter(isEven)); + +/* console.log('numbers.reduce', + numbers.reduce(function(previous, current, index) { + return previous + current; + }) +); */ // ES5 sintax for function below + +console.log('numbers.reduce', numbers.reduce((previous, current) => previous + current)); diff --git a/chapter01/11-ES6letconst.html b/examples/chapter03/06-ES2015Methods.html old mode 100644 new mode 100755 similarity index 59% rename from chapter01/11-ES6letconst.html rename to examples/chapter03/06-ES2015Methods.html index e57da24c..cd7abd9c --- a/chapter01/11-ES6letconst.html +++ b/examples/chapter03/06-ES2015Methods.html @@ -5,7 +5,6 @@ - - + - \ No newline at end of file + diff --git a/examples/chapter03/06-ES2015Methods.js b/examples/chapter03/06-ES2015Methods.js new file mode 100755 index 00000000..6513e2d3 --- /dev/null +++ b/examples/chapter03/06-ES2015Methods.js @@ -0,0 +1,117 @@ +// @ts-check + +const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + +//* ********* using for..of loop +for (const n of numbers) { + console.log(`for..of loop: ${n} % 2 === 0`, n % 2 === 0 ? 'even' : 'odd'); +} + +//* ********* Using the new ES6 iterator (@@iterator) +console.log('Using the new ES6 iterator (@@iterator)'); + +let iterator = numbers[Symbol.iterator](); +console.log('iterator.next().value', iterator.next().value); // 1 +console.log('iterator.next().value', iterator.next().value); // 2 +console.log('iterator.next().value', iterator.next().value); // 3 +console.log('iterator.next().value', iterator.next().value); // 4 +console.log('iterator.next().value', iterator.next().value); // 5 + +// or use code below +iterator = numbers[Symbol.iterator](); +for (const n of iterator) { + console.log(`${n} of iterator`, n); +} + +//* ********* Array entries, keys and values +console.log('Array entries, keys and values'); + +console.log('Array.entries'); +let aEntries = numbers.entries(); // retrieve iterator of key/value +console.log('aEntries.next().value', aEntries.next().value); // [0, 1] - position 0, value 1 +console.log('aEntries.next().value', aEntries.next().value); // [1, 2] - position 1, value 2 +console.log('aEntries.next().value', aEntries.next().value); // [2, 3] - position 2, value 3 + +// or use code below +aEntries = numbers.entries(); +for (const n of aEntries) { + console.log(`entry of ${n}`, n); +} + +console.log('Array.keys'); +const aKeys = numbers.keys(); // retrieve iterator of keys +console.log('aKeys.next()', aKeys.next()); // {value: 0, done: false } done false means iterator has more values +console.log('aKeys.next()', aKeys.next()); // {value: 1, done: false } +console.log('aKeys.next()', aKeys.next()); // {value: 2, done: false } + +console.log('Array.values - Only Edge and Safari - Oct 2017'); +// const aValues = numbers.values(); +// console.log(aValues.next()); // {value: 1, done: false } done false means iterator has more values +// console.log(aValues.next()); // {value: 2, done: false } +// console.log(aValues.next()); // {value: 3, done: false } + +//* ********* Using the from method +console.log('Using the from method'); + +const evens = Array.from(numbers, x => x % 2 === 0); +console.log('Array.from(numbers, x => x % 2 === 0)', evens); + +const numbers2 = Array.from(numbers); +console.log('Array.from(numbers)', numbers2); + +//* ********* Using Array.of +console.log('Using Array.of'); + +const numbers3 = Array.of(1); +const numbers4 = Array.of(1, 2, 3, 4, 5, 6); +const numbersCopy = Array.of(...numbers4); +console.log('Array.of(1)', numbers3); +console.log('Array.of(1, 2, 3, 4, 5, 6)', numbers4); +console.log('Array.of(...numbers4)', numbersCopy); + +//* ********* Using the fill method +console.log('Using the fill method'); + +numbersCopy.fill(0); +console.log('numbersCopy.fill(0)', numbersCopy); + +numbersCopy.fill(2, 1); +console.log('numbersCopy.fill(2, 1)', numbersCopy); + +numbersCopy.fill(1, 3, 5); +console.log('numbersCopy.fill(1, 3, 5)', numbersCopy); + +const ones = Array(6).fill(1); +console.log('Array(6).fill(1)', ones); + +//* ********* Using the copyWithin method +console.log('Using the copyWithin method'); + +let copyArray = [1, 2, 3, 4, 5, 6]; +console.log('copyArray', copyArray); + +copyArray = copyArray.copyWithin(0, 3); // pos 3 value is copied to pos 0 +console.log('copyArray.copyWithin(0, 3)', copyArray); + +copyArray = [1, 2, 3, 4, 5, 6]; +copyArray = copyArray.copyWithin(1, 3, 5); // pos 3-4 values are copied to pos 1-2 +console.log('copyArray.copyWithin(1, 3, 5)', copyArray); + +//* ********* methods find and findIndex +console.log('methods find and findIndex'); + +function multipleOf13(element) { + return element % 13 === 0; +} + +console.log('numbers.find(multipleOf13)', numbers.find(multipleOf13)); +console.log('numbers.findIndex(multipleOf13)', numbers.findIndex(multipleOf13)); + +//* ********* EcmaScript 2016 (ES7): using the method includes +console.log('EcmaScript 2016 (ES7): using the method includes'); + +console.log('numbers.includes(15)', numbers.includes(15)); +console.log('numbers.includes(20)', numbers.includes(20)); + +const numbers5 = [7, 6, 5, 4, 3, 2, 1]; +console.log('numbers5.includes(4, 5)', numbers5.includes(4, 5)); diff --git a/chapter06/04-UsingES6Set.html b/examples/chapter03/07-Sorting.html similarity index 61% rename from chapter06/04-UsingES6Set.html rename to examples/chapter03/07-Sorting.html index a08e635c..0e32a5b2 100644 --- a/chapter06/04-UsingES6Set.html +++ b/examples/chapter03/07-Sorting.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter03/07-Sorting.js b/examples/chapter03/07-Sorting.js new file mode 100644 index 00000000..f9efe1df --- /dev/null +++ b/examples/chapter03/07-Sorting.js @@ -0,0 +1,71 @@ +// @ts-check + +let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; +console.log('numbers', numbers); + + +numbers = numbers.reverse(); +console.log('numbers.reverse()', numbers); + +console.log('numbers.sort()', numbers.sort()); + +/* console.log( + numbers.sort(function(a, b) { + return a - b; + }) +); */ // ES5 syntax + +console.log('numbers.sort((a, b) => a - b)', numbers.sort((a, b) => a - b)); + +function compare(a, b) { + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + // a must be equal to b + return 0; +} + +console.log('numbers.sort(compare)', numbers.sort(compare)); + +// Sorting objects +const friends = [ + { name: 'John', age: 30 }, + { name: 'Ana', age: 20 }, + { name: 'Chris', age: 25 }, // trailing comma ES2017 +]; + +function comparePerson(a, b) { + if (a.age < b.age) { + return -1; + } + if (a.age > b.age) { + return 1; + } + return 0; +} + +console.log('friends.sort(comparePerson)', friends.sort(comparePerson)); + +let names = ['Ana', 'ana', 'john', 'John']; +console.log('names', names); +console.log('names.sort()', names.sort()); + +names = ['Ana', 'ana', 'john', 'John']; // reset to array original state +console.log('names.sort(compareFunction)', names.sort((a, b) => { + if (a.toLowerCase() < b.toLowerCase()) { + return -1; + } + if (a.toLowerCase() > b.toLowerCase()) { + return 1; + } + return 0; +})); +names = ['Ana', 'ana', 'john', 'John']; // reset to array original state +console.log('names.sort((a, b) => a.localeCompare(b))', names.sort((a, b) => a.localeCompare(b))); + +const names2 = ['Maève', 'Maeve']; +console.log('names2', names); +console.log('names2.sort((a, b) => a.localeCompare(b))', names2.sort((a, b) => a.localeCompare(b))); diff --git a/chapter01/16-ES6Classes.html b/examples/chapter03/08-Searching.html similarity index 60% rename from chapter01/16-ES6Classes.html rename to examples/chapter03/08-Searching.html index 15a8f004..6dd9aac1 100644 --- a/chapter01/16-ES6Classes.html +++ b/examples/chapter03/08-Searching.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter03/08-Searching.js b/examples/chapter03/08-Searching.js new file mode 100644 index 00000000..1388a873 --- /dev/null +++ b/examples/chapter03/08-Searching.js @@ -0,0 +1,17 @@ +// @ts-check + +const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; +console.log('numbers', numbers); + +//* ** toString +console.log('numbers.toString()', numbers.toString()); + +console.log('numbers.indexOf(10)', numbers.indexOf(10)); +console.log('numbers.indexOf(100)', numbers.indexOf(100)); + +numbers.push(10); +console.log('push 10: numbers.lastIndexOf(10)', numbers.lastIndexOf(10)); +console.log('push 10: numbers.lastIndexOf(100)', numbers.lastIndexOf(100)); + +const numbersString = numbers.join('-'); +console.log('numbers.join("-")', numbersString); diff --git a/chapter02/07-TypedArrays.html b/examples/chapter03/09-TypedArrays.html old mode 100644 new mode 100755 similarity index 60% rename from chapter02/07-TypedArrays.html rename to examples/chapter03/09-TypedArrays.html index 5e021e79..9257fe4a --- a/chapter02/07-TypedArrays.html +++ b/examples/chapter03/09-TypedArrays.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter03/09-TypedArrays.js b/examples/chapter03/09-TypedArrays.js new file mode 100755 index 00000000..be92f508 --- /dev/null +++ b/examples/chapter03/09-TypedArrays.js @@ -0,0 +1,24 @@ +const length = 5; +const int16 = new Int16Array(length); + +const array16 = []; +array16.length = length; + +for (let i = 0; i < length; i++) { + int16[i] = i + 1; +} + +console.log(int16); + +// Int8Array(); +// Uint8Array(); +// Uint8ClampedArray(); +// Int16Array(); +// Uint16Array(); +// Int32Array(); +// Uint32Array(); +// Float32Array(); +// Float64Array(); + +// http://www.html5rocks.com/en/tutorials/webgl/typed_arrays/ +// http://www.i-programmer.info/programming/javascript/6135-javascript-data-structures-typed-arrays.html diff --git a/examples/chapter03/10-ArraysAndTypeScript.ts b/examples/chapter03/10-ArraysAndTypeScript.ts new file mode 100644 index 00000000..63e97f2e --- /dev/null +++ b/examples/chapter03/10-ArraysAndTypeScript.ts @@ -0,0 +1,32 @@ +// const numbers: number[]; +const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; +console.log('numbers', numbers); + +// let names: string[]; +let names = ['Ana', 'ana', 'john', 'John']; +console.log('names', names); +console.log('names.sort()', names.sort()); + +interface Person { + name: string; + age: number; +} + +// const friends: {name: string, age: number}[]; +const friends = [ + { name: 'John', age: 30 }, + { name: 'Ana', age: 20 }, + { name: 'Chris', age: 25 }, // trailing comma ES2017 +]; + +function comparePerson(a: Person, b: Person) { + if (a.age < b.age) { + return -1; + } + if (a.age > b.age) { + return 1; + } + return 0; +} + +console.log('friends.sort(comparePerson)', friends.sort(comparePerson)); diff --git a/examples/chapter04/01-Stack.html b/examples/chapter04/01-Stack.html new file mode 100755 index 00000000..3025a012 --- /dev/null +++ b/examples/chapter04/01-Stack.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + diff --git a/examples/chapter04/01-Stack.js b/examples/chapter04/01-Stack.js new file mode 100755 index 00000000..d3994b08 --- /dev/null +++ b/examples/chapter04/01-Stack.js @@ -0,0 +1,33 @@ +// import Stack from './../../src/js/data-structures/stack.js'; // ES2015 modules +// import StackArray from './../../src/js/data-structures/stack-array.js'; // ES2015 modules +// const Stack = require('../../dist/js/data-structures/stack'); // for node +// const Stack = stack; // older browsers - remove from html script import: type="module" +const { Stack } = PacktDataStructuresAlgorithms; + +const stack = new Stack(); // new StackArray(); + +// using WeakMap to store Stack items we ensure true privacy +// console.log(Object.getOwnPropertyNames(stack)); +// console.log(Object.keys(stack)); +// console.log(stack.items); + +console.log('stack.isEmpty() => ', stack.isEmpty()); // outputs true + +stack.push(5); +stack.push(8); + +console.log('stack after push 5 and 8 => ', stack.toString()); + +console.log('stack.peek() => ', stack.peek()); // outputs 8 + +stack.push(11); + +console.log('stack.size() after push 11 => ', stack.size()); // outputs 3 +console.log('stack.isEmpty() => ', stack.isEmpty()); // outputs false + +stack.push(15); + +stack.pop(); +stack.pop(); + +console.log('stack.size() after push 15 and pop twice => ', stack.size()); // outputs 2 diff --git a/examples/chapter04/01-StackSymbol.js b/examples/chapter04/01-StackSymbol.js new file mode 100755 index 00000000..c525f359 --- /dev/null +++ b/examples/chapter04/01-StackSymbol.js @@ -0,0 +1,47 @@ +const _items = Symbol('stackItems'); + +class Stack { + constructor() { + this[_items] = []; + } + + push(element) { + this[_items].push(element); + } + + pop() { + return this[_items].pop(); + } + + peek() { + return this[_items][this[_items].length - 1]; + } + + isEmpty() { + return this[_items].length === 0; + } + + size() { + return this[_items].length; + } + + clear() { + this[_items] = []; + } + + print() { + console.log(this.toString()); + } + + toString() { + return this[_items].toString(); + } +} + +const stack = new Stack(); +const objectSymbols = Object.getOwnPropertySymbols(stack); +console.log(objectSymbols.length); // 1 +console.log(objectSymbols); // [Symbol()] +console.log(objectSymbols[0]); // Symbol() +stack[objectSymbols[0]].push(1); +stack.print(); // 5, 8, 1 diff --git a/examples/chapter04/01-StackWeakMap.js b/examples/chapter04/01-StackWeakMap.js new file mode 100644 index 00000000..7471b8d1 --- /dev/null +++ b/examples/chapter04/01-StackWeakMap.js @@ -0,0 +1,70 @@ +// @ts-check + + +const _items = new WeakMap(); +const _count = new WeakMap(); + +class Stack { + constructor() { + _count.set(this, 0); + _items.set(this, {}); + } + + push(element) { + const items = _items.get(this); + const count = _count.get(this); + items[count] = element; + _count.set(this, count + 1); + } + + pop() { + if (this.isEmpty()) { + return undefined; + } + const items = _items.get(this); + let count = _count.get(this); + count--; + _count.set(this, count); + const result = items[count]; + delete items[count]; + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + const items = _items.get(this); + const count = _count.get(this); + return items[count - 1]; + } + + isEmpty() { + return _count.get(this) === 0; + } + + size() { + return _count.get(this); + } + + clear() { + /* while (!this.isEmpty()) { + this.pop(); + } */ + _count.set(this, 0); + _items.set(this, {}); + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const items = _items.get(this); + const count = _count.get(this); + let objString = `${items[0]}`; + for (let i = 1; i < count; i++) { + objString = `${objString},${items[i]}`; + } + return objString; + } +} diff --git a/examples/chapter04/02-BalancedSymbols.html b/examples/chapter04/02-BalancedSymbols.html new file mode 100755 index 00000000..f2aea40d --- /dev/null +++ b/examples/chapter04/02-BalancedSymbols.html @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/examples/chapter04/02-BalancedSymbols.js b/examples/chapter04/02-BalancedSymbols.js new file mode 100755 index 00000000..614f44e7 --- /dev/null +++ b/examples/chapter04/02-BalancedSymbols.js @@ -0,0 +1,5 @@ +const { parenthesesChecker } = PacktDataStructuresAlgorithms; + +console.log('{([])}', parenthesesChecker('{([])}')); // true +console.log('{{([][])}()}', parenthesesChecker('{{([][])}()}')); // true +console.log('[{()]', parenthesesChecker('[{()]')); // false diff --git a/examples/chapter04/03-DecimalToBinary.html b/examples/chapter04/03-DecimalToBinary.html new file mode 100755 index 00000000..88b6c362 --- /dev/null +++ b/examples/chapter04/03-DecimalToBinary.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter04/03-DecimalToBinary.js b/examples/chapter04/03-DecimalToBinary.js new file mode 100755 index 00000000..f39fcb1d --- /dev/null +++ b/examples/chapter04/03-DecimalToBinary.js @@ -0,0 +1,13 @@ +const { decimalToBinary } = PacktDataStructuresAlgorithms; +const { baseConverter } = PacktDataStructuresAlgorithms; + +// 233 == 11101001 +// 2x(10x10) + 3x(10) + 3x(1) +console.log(decimalToBinary(233)); // 11101001 +console.log(decimalToBinary(10)); // 1010 +console.log(decimalToBinary(1000)); // 1111101000 + +console.log(baseConverter(100345, 2)); // 11000011111111001 +console.log(baseConverter(100345, 8)); // 303771 +console.log(baseConverter(100345, 16)); // 187F9 +console.log(baseConverter(100345, 35)); // 2BW0 diff --git a/examples/chapter04/04-TowerOfHanoi.html b/examples/chapter04/04-TowerOfHanoi.html new file mode 100755 index 00000000..f6d0cb52 --- /dev/null +++ b/examples/chapter04/04-TowerOfHanoi.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter04/04-TowerOfHanoi.js b/examples/chapter04/04-TowerOfHanoi.js new file mode 100755 index 00000000..f5d85cf7 --- /dev/null +++ b/examples/chapter04/04-TowerOfHanoi.js @@ -0,0 +1,6 @@ +const { hanoiStack } = PacktDataStructuresAlgorithms; +const { hanoi } = PacktDataStructuresAlgorithms; + +console.log(hanoiStack(3)); + +console.log(hanoi(3, 'source', 'helper', 'dest')); diff --git a/examples/chapter05/01-Queue.html b/examples/chapter05/01-Queue.html new file mode 100755 index 00000000..2e67f7f4 --- /dev/null +++ b/examples/chapter05/01-Queue.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter05/01-Queue.js b/examples/chapter05/01-Queue.js new file mode 100755 index 00000000..852a1b4d --- /dev/null +++ b/examples/chapter05/01-Queue.js @@ -0,0 +1,14 @@ +const { Queue } = PacktDataStructuresAlgorithms; + +const queue = new Queue(); +console.log(queue.isEmpty()); // outputs true +queue.enqueue('John'); +queue.enqueue('Jack'); +console.log(queue.toString()); // John,Jack +queue.enqueue('Camila'); +console.log(queue.toString()); // John,Jack,Camila +console.log(queue.size()); // outputs 3 +console.log(queue.isEmpty()); // outputs false +queue.dequeue(); // remove John +queue.dequeue(); // remove Jack +console.log(queue.toString()); // Camila diff --git a/examples/chapter05/02-Deque.html b/examples/chapter05/02-Deque.html new file mode 100755 index 00000000..99b838af --- /dev/null +++ b/examples/chapter05/02-Deque.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter05/02-Deque.js b/examples/chapter05/02-Deque.js new file mode 100755 index 00000000..4c84b6de --- /dev/null +++ b/examples/chapter05/02-Deque.js @@ -0,0 +1,17 @@ +const { Deque } = PacktDataStructuresAlgorithms; + +const deque = new Deque(); +console.log(deque.isEmpty()); // outputs true +deque.addBack('John'); +deque.addBack('Jack'); +console.log(deque.toString()); // John,Jack +deque.addBack('Camila'); +console.log(deque.toString()); // John,Jack,Camila +console.log(deque.size()); // outputs 3 +console.log(deque.isEmpty()); // outputs false +deque.removeFront(); // remove John +console.log(deque.toString()); // Jack,Camila +deque.removeBack(); // Camila decides to leave +console.log(deque.toString()); // Jack +deque.addFront('John'); // John comes back for information +console.log(deque.toString()); // John,Jack diff --git a/examples/chapter05/03-HotPotato.html b/examples/chapter05/03-HotPotato.html new file mode 100755 index 00000000..85d45104 --- /dev/null +++ b/examples/chapter05/03-HotPotato.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter05/03-HotPotato.js b/examples/chapter05/03-HotPotato.js new file mode 100755 index 00000000..686f6791 --- /dev/null +++ b/examples/chapter05/03-HotPotato.js @@ -0,0 +1,16 @@ +const { hotPotato } = PacktDataStructuresAlgorithms; + +const names = ['John', 'Jack', 'Camila', 'Ingrid', 'Carl']; +const result = hotPotato(names, 7); + +result.eliminated.forEach(name => { + console.log(`${name} was eliminated from the Hot Potato game.`); +}); + +console.log(`The winner is: ${result.winner}`); + +// Camila was eliminated from the Hot Potato game. +// Jack was eliminated from the Hot Potato game. +// Carl was eliminated from the Hot Potato game. +// Ingrid was eliminated from the Hot Potato game. +// The winner is: John diff --git a/examples/chapter05/04-PalindromeChecker.html b/examples/chapter05/04-PalindromeChecker.html new file mode 100755 index 00000000..785e0482 --- /dev/null +++ b/examples/chapter05/04-PalindromeChecker.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter05/04-PalindromeChecker.js b/examples/chapter05/04-PalindromeChecker.js new file mode 100755 index 00000000..99c29cf9 --- /dev/null +++ b/examples/chapter05/04-PalindromeChecker.js @@ -0,0 +1,8 @@ +const { palindromeChecker } = PacktDataStructuresAlgorithms; + +console.log('a', palindromeChecker('a')); +console.log('aa', palindromeChecker('aa')); +console.log('kayak', palindromeChecker('kayak')); +console.log('level', palindromeChecker('level')); +console.log('Was it a car or a cat I saw', palindromeChecker('Was it a car or a cat I saw')); +console.log('Step on no pets', palindromeChecker('Step on no pets')); diff --git a/examples/chapter06/01-LinkedList.html b/examples/chapter06/01-LinkedList.html new file mode 100644 index 00000000..df7c5591 --- /dev/null +++ b/examples/chapter06/01-LinkedList.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter06/01-LinkedList.js b/examples/chapter06/01-LinkedList.js new file mode 100644 index 00000000..8d7c6e49 --- /dev/null +++ b/examples/chapter06/01-LinkedList.js @@ -0,0 +1,48 @@ +const { LinkedList } = PacktDataStructuresAlgorithms; + +const list = new LinkedList(); + +console.log('push element 15'); +list.push(15); + +console.log('list.indexOf(15) => ', list.indexOf(15)); + +console.log('push element 10'); +list.push(10); + +console.log('list.toString() => ', list.toString()); +console.log('list.indexOf(10) => ', list.indexOf(10)); + +console.log('push element 13'); +list.push(13); + +console.log('list.toString() => ', list.toString()); +console.log('list.indexOf(13) => ', list.indexOf(13)); +console.log('list.indexOf(10) => ', list.indexOf(10)); + +console.log('push elements 11 and 12'); +list.push(11); +list.push(12); + +console.log('list.toString() => ', list.toString()); +console.log('list.removeAt(1) => ', list.removeAt(1)); +console.log('list.toString() => ', list.toString()); +console.log('list.removeAt(3) => ', list.removeAt(3)); +console.log('list.toString() => ', list.toString()); + +console.log('push element 14'); +list.push(14); + +console.log('list.toString() => ', list.toString()); +console.log('insert element 16 pos 0 => ', list.insert(16, 0)); +console.log('list.toString() => ', list.toString()); +console.log('insert element 17 pos 1 => ', list.insert(17, 1)); +console.log('list.toString() => ', list.toString()); +console.log('insert element 18 pos list.size() => ', list.insert(18, list.size())); +console.log('list.toString() => ', list.toString()); +console.log('remove element 16 => ', list.remove(16)); +console.log('list.toString() => ', list.toString()); +console.log('remove element 11 => ', list.remove(11)); +console.log('list.toString() => ', list.toString()); +console.log('remove element 18 => ', list.remove(18)); +console.log('list.toString() => ', list.toString()); diff --git a/examples/chapter06/02-DoublyLinkedList.html b/examples/chapter06/02-DoublyLinkedList.html new file mode 100644 index 00000000..1aea7c24 --- /dev/null +++ b/examples/chapter06/02-DoublyLinkedList.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter06/02-DoublyLinkedList.js b/examples/chapter06/02-DoublyLinkedList.js new file mode 100644 index 00000000..333f701c --- /dev/null +++ b/examples/chapter06/02-DoublyLinkedList.js @@ -0,0 +1,54 @@ +const { DoublyLinkedList } = PacktDataStructuresAlgorithms; + +const list = new DoublyLinkedList(); + +console.log('push element 15'); +list.push(15); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('push element 16'); +list.push(16); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('push element 17'); +list.push(17); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('insert element 13 pos 0 => ', list.insert(13, 0)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('insert element 18 pos 4 => ', list.insert(18, 4)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('insert element 14 pos 1 => ', list.insert(14, 1)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('list.removeAt(0) => ', list.removeAt(0)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('list.removeAt(list.size() - 1) => ', list.removeAt(list.size() - 1)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('list.removeAt(1) => ', list.removeAt(1)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('remove element 16 => ', list.remove(16)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('remove element 14 => ', list.remove(14)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); + +console.log('remove element 17 => ', list.remove(17)); +console.log('list.toString() => ', list.toString()); +console.log('list.inverseToString() => ', list.inverseToString()); diff --git a/examples/chapter06/03-CircularLinkedList.html b/examples/chapter06/03-CircularLinkedList.html new file mode 100644 index 00000000..10fbd6b6 --- /dev/null +++ b/examples/chapter06/03-CircularLinkedList.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter06/03-CircularLinkedList.js b/examples/chapter06/03-CircularLinkedList.js new file mode 100644 index 00000000..05178956 --- /dev/null +++ b/examples/chapter06/03-CircularLinkedList.js @@ -0,0 +1,32 @@ +const { CircularLinkedList } = PacktDataStructuresAlgorithms; + +const list = new CircularLinkedList(); + +console.log('push element 15'); +list.push(15); +console.log('list.toString() => ', list.toString()); + +console.log('push element 16'); +list.push(16); +console.log('list.toString() => ', list.toString()); + +console.log('insert element 14 pos 0 => ', list.insert(14, 0)); +console.log('list.toString() => ', list.toString()); + +console.log('insert element 14.5 pos 1 => ', list.insert(14.5, 1)); +console.log('list.toString() => ', list.toString()); + +console.log('insert element 17 pos 4 => ', list.insert(17, 4)); +console.log('list.toString() => ', list.toString()); + +console.log('list.removeAt(0) => ', list.removeAt(0)); +console.log('list.toString() => ', list.toString()); + +console.log('list.removeAt(1) => ', list.removeAt(1)); +console.log('list.toString() => ', list.toString()); + +console.log('list.removeAt(2) => ', list.removeAt(2)); +console.log('list.toString() => ', list.toString()); + +console.log('list.indexOf(14.5) => ', list.indexOf(14.5)); +console.log('list.indexOf(16) => ', list.indexOf(16)); diff --git a/examples/chapter06/04-SortedLinkedList.html b/examples/chapter06/04-SortedLinkedList.html new file mode 100644 index 00000000..9feb1a70 --- /dev/null +++ b/examples/chapter06/04-SortedLinkedList.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter06/04-SortedLinkedList.js b/examples/chapter06/04-SortedLinkedList.js new file mode 100644 index 00000000..c6351f8f --- /dev/null +++ b/examples/chapter06/04-SortedLinkedList.js @@ -0,0 +1,53 @@ +const { SortedLinkedList } = PacktDataStructuresAlgorithms; +const { util } = PacktDataStructuresAlgorithms; + +const list = new SortedLinkedList(); + +console.log(''); +for (let i = 5; i > 0; i--) { + list.push(i); +} + +console.log('list after pushing 5, 4, 3, 2, and 1 => ', list.toString()); + +console.log('list.removeAt(1) => ', list.removeAt(1)); + +console.log('remove element 16 => ', list.remove(5)); + +console.log('list.toString() => ', list.toString()); + +// ------- Example 02 + +class MyObj { + constructor(el1, el2) { + this.el1 = el1; + this.el2 = el2; + } + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } +} + +function myObjCompare(a, b) { + return a.toString().localeCompare(b.toString()); +} + +const ds = new SortedLinkedList(util.defaultEquals, myObjCompare); + +console.log('*** SortedLinkedList with custom sorting function'); + +ds.push(new MyObj(3, 4)); +console.log('push MyObj(3, 4)'); +console.log('list.toString() => ', ds.toString()); + +ds.push(new MyObj(1, 2)); +console.log('push MyObj(1, 2)'); +console.log('list.toString() => ', ds.toString()); + +ds.push(new MyObj(5, 6)); +console.log('push MyObj(5, 6)'); +console.log('list.toString() => ', ds.toString()); + +ds.insert(new MyObj(0, 0), 4); +console.log('insert MyObj(0, 0) pos 4 (pos ignored)'); +console.log('list.toString() => ', ds.toString()); diff --git a/examples/chapter06/05-StackLinkedList.html b/examples/chapter06/05-StackLinkedList.html new file mode 100644 index 00000000..c511e977 --- /dev/null +++ b/examples/chapter06/05-StackLinkedList.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter06/05-StackLinkedList.js b/examples/chapter06/05-StackLinkedList.js new file mode 100644 index 00000000..866e7f91 --- /dev/null +++ b/examples/chapter06/05-StackLinkedList.js @@ -0,0 +1,24 @@ +const { StackLinkedList } = PacktDataStructuresAlgorithms; + +const stack = new StackLinkedList(); + +console.log('stack.isEmpty() => ', stack.isEmpty()); // outputs true + +stack.push(5); +stack.push(8); + +console.log('stack after push 5 and 8 => ', stack.toString()); + +console.log('stack.peek() => ', stack.peek()); // outputs 8 + +stack.push(11); + +console.log('stack.size() after push 11 => ', stack.size()); // outputs 3 +console.log('stack.isEmpty() => ', stack.isEmpty()); // outputs false + +stack.push(15); + +stack.pop(); +stack.pop(); + +console.log('stack.size() after push 15 and pop twice => ', stack.size()); // outputs 2 diff --git a/examples/chapter07/01-Set.html b/examples/chapter07/01-Set.html new file mode 100755 index 00000000..cf2f575b --- /dev/null +++ b/examples/chapter07/01-Set.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter07/01-Set.js b/examples/chapter07/01-Set.js new file mode 100755 index 00000000..e893c2c8 --- /dev/null +++ b/examples/chapter07/01-Set.js @@ -0,0 +1,19 @@ +const { Set } = PacktDataStructuresAlgorithms; + +const set = new Set(); + +set.add(1); +console.log(set.values()); // outputs [1] +console.log(set.has(1)); // outputs true +console.log(set.size()); // outputs 1 + +set.add(2); +console.log(set.values()); // outputs [1, 2] +console.log(set.has(2)); // true +console.log(set.size()); // 2 + +set.delete(1); +console.log(set.values()); // outputs [2] + +set.delete(2); +console.log(set.values()); // outputs [] diff --git a/examples/chapter07/02-SetOperations.html b/examples/chapter07/02-SetOperations.html new file mode 100755 index 00000000..b55d7e0d --- /dev/null +++ b/examples/chapter07/02-SetOperations.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter07/02-SetOperations.js b/examples/chapter07/02-SetOperations.js new file mode 100755 index 00000000..2608c7ef --- /dev/null +++ b/examples/chapter07/02-SetOperations.js @@ -0,0 +1,66 @@ +const { Set } = PacktDataStructuresAlgorithms; + +// --------- Union ---------- + +let setA = new Set(); +setA.add(1); +setA.add(2); +setA.add(3); + +let setB = new Set(); +setB.add(3); +setB.add(4); +setB.add(5); +setB.add(6); + +const unionAB = setA.union(setB); +console.log(unionAB.values()); // [1, 2, 3, 4, 5, 6] + +// --------- Intersection ---------- + +setA = new Set(); +setA.add(1); +setA.add(2); +setA.add(3); + +setB = new Set(); +setB.add(2); +setB.add(3); +setB.add(4); + +const intersectionAB = setA.intersection(setB); +console.log(intersectionAB.values()); // [2, 3] + +// --------- Difference ---------- + +setA = new Set(); +setA.add(1); +setA.add(2); +setA.add(3); + +setB = new Set(); +setB.add(2); +setB.add(3); +setB.add(4); + +const differenceAB = setA.difference(setB); +console.log(differenceAB.values()); // [1] + +// --------- Subset ---------- + +setA = new Set(); +setA.add(1); +setA.add(2); + +setB = new Set(); +setB.add(1); +setB.add(2); +setB.add(3); + +const setC = new Set(); +setC.add(2); +setC.add(3); +setC.add(4); + +console.log(setA.isSubsetOf(setB)); // true +console.log(setA.isSubsetOf(setC)); // false diff --git a/examples/chapter07/03-ES2015Set.html b/examples/chapter07/03-ES2015Set.html new file mode 100755 index 00000000..7fe40e1b --- /dev/null +++ b/examples/chapter07/03-ES2015Set.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter07/03-ES2015Set.js b/examples/chapter07/03-ES2015Set.js new file mode 100755 index 00000000..721ea4d1 --- /dev/null +++ b/examples/chapter07/03-ES2015Set.js @@ -0,0 +1,72 @@ +const set = new Set(); + +set.add(1); +console.log(set.values()); // outputs @Iterator +console.log(set.has(1)); // outputs true +console.log(set.size); // outputs 1 + +set.add(2); +console.log(set.values()); // outputs [1, 2] +console.log(set.has(2)); // true +console.log(set.size); // 2 + +set.delete(1); +console.log(set.values()); // outputs [2] + +set.delete(2); +console.log(set.values()); // outputs [] + +const setA = new Set(); +setA.add(1); +setA.add(2); +setA.add(3); + +const setB = new Set(); +setB.add(2); +setB.add(3); +setB.add(4); + +// --------- Union ---------- +const union = (set1, set2) => { + const unionAb = new Set(); + set1.forEach(value => unionAb.add(value)); + set2.forEach(value => unionAb.add(value)); + return unionAb; +}; +console.log(union(setA, setB)); + +console.log(new Set([...setA, ...setB])); + +// --------- Intersection ---------- +const intersection = (set1, set2) => { + const intersectionSet = new Set(); + set1.forEach(value => { + if (set2.has(value)) { + intersectionSet.add(value); + } + }); + return intersectionSet; +}; +console.log(intersection(setA, setB)); + +console.log(new Set([...setA].filter(x => setB.has(x)))); + +// alternative - works on FF only +// console.log(new Set([x for (x of setA) if (setB.has(x))])); + +// --------- Difference ---------- +const difference = (set1, set2) => { + const differenceSet = new Set(); + set1.forEach(value => { + if (!set2.has(value)) { + differenceSet.add(value); + } + }); + return differenceSet; +}; +console.log(difference(setA, setB)); + +console.log(new Set([...setA].filter(x => !setB.has(x)))); + +// alternative - works on FF only +// console.log(new Set([x for (x of setA) if (!setB.has(x))])); diff --git a/examples/chapter08/01-Dictionaries.html b/examples/chapter08/01-Dictionaries.html new file mode 100755 index 00000000..d972458c --- /dev/null +++ b/examples/chapter08/01-Dictionaries.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter08/01-Dictionaries.js b/examples/chapter08/01-Dictionaries.js new file mode 100755 index 00000000..53433cc0 --- /dev/null +++ b/examples/chapter08/01-Dictionaries.js @@ -0,0 +1,28 @@ +const { Dictionary } = PacktDataStructuresAlgorithms; + +const dictionary = new Dictionary(); + +dictionary.set('Gandalf', 'gandalf@email.com'); +dictionary.set('John', 'johnsnow@email.com'); +dictionary.set('Tyrion', 'tyrion@email.com'); + +console.log(dictionary.hasKey('Gandalf')); // true +console.log(dictionary.size()); // 3 + +console.log(dictionary.keys()); // ["Gandalf", "John", "Tyrion"] +console.log(dictionary.values()); // ["gandalf@email.com", "johnsnow@email.com", "tyrion@email.com"] +console.log(dictionary.get('Tyrion')); // tyrion@email.com + +dictionary.remove('John'); + +console.log(dictionary.keys()); // ["Gandalf", "Tyrion"] +console.log(dictionary.values()); // ["gandalf@email.com", "tyrion@email.com"] + +console.log(dictionary.keyValues()); // [{key: "Gandalf", value: "gandalf@email.com"}, {key: "Tyrion", value: "tyrion@email.com"}] +console.log(dictionary.toString()); // [#Gandalf: gandalf@email.com],[#Tyrion: tyrion@email.com] + +dictionary.forEach((k, v) => { + console.log('forEach: ', `key: ${k}, value: ${v}`); +}); +// forEach: key: Gandalf, value: gandalf@email.com +// forEach: key: Tyrion, value: tyrion@email.com diff --git a/examples/chapter08/02-HashTable.html b/examples/chapter08/02-HashTable.html new file mode 100755 index 00000000..67ad128c --- /dev/null +++ b/examples/chapter08/02-HashTable.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter08/02-HashTable.js b/examples/chapter08/02-HashTable.js new file mode 100755 index 00000000..fbee2022 --- /dev/null +++ b/examples/chapter08/02-HashTable.js @@ -0,0 +1,51 @@ +const { HashTable } = PacktDataStructuresAlgorithms; + +const hash = new HashTable(); + +console.log(hash.hashCode('Gandalf') + ' - Gandalf'); +console.log(hash.hashCode('John') + ' - John'); +console.log(hash.hashCode('Tyrion') + ' - Tyrion'); + +console.log(' '); + +console.log(hash.hashCode('Ygritte') + ' - Ygritte'); +console.log(hash.hashCode('Jonathan') + ' - Jonathan'); +console.log(hash.hashCode('Jamie') + ' - Jamie'); +console.log(hash.hashCode('Jack') + ' - Jack'); +console.log(hash.hashCode('Jasmine') + ' - Jasmine'); +console.log(hash.hashCode('Jake') + ' - Jake'); +console.log(hash.hashCode('Nathan') + ' - Nathan'); +console.log(hash.hashCode('Athelstan') + ' - Athelstan'); +console.log(hash.hashCode('Sue') + ' - Sue'); +console.log(hash.hashCode('Aethelwulf') + ' - Aethelwulf'); +console.log(hash.hashCode('Sargeras') + ' - Sargeras'); + +hash.put('Ygritte', 'ygritte@email.com'); +hash.put('Jonathan', 'jonathan@email.com'); +hash.put('Jamie', 'jamie@email.com'); +hash.put('Jack', 'jack@email.com'); +hash.put('Jasmine', 'jasmine@email.com'); +hash.put('Jake', 'jake@email.com'); +hash.put('Nathan', 'nathan@email.com'); +hash.put('Athelstan', 'athelstan@email.com'); +hash.put('Sue', 'sue@email.com'); +hash.put('Aethelwulf', 'aethelwulf@email.com'); +hash.put('Sargeras', 'sargeras@email.com'); + +console.log('**** Printing Hash **** '); + +console.log(hash.toString()); +// {4 => [#Ygritte: ygritte@email.com]},{5 => [#Aethelwulf: aethelwulf@email.com]},{7 => [#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Sargeras: sargeras@email.com]} + +console.log('**** Get **** '); + +console.log(hash.get('Ygritte')); // ygritte@email.com +console.log(hash.get('Loiane')); // jasmine@email.com + +console.log('**** Remove **** '); + +hash.remove('Ygritte'); +console.log(hash.get('Ygritte')); // undefined + +console.log(hash.toString()); +// {5 => [#Aethelwulf: aethelwulf@email.com]},{7 => [#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Sargeras: sargeras@email.com]} diff --git a/examples/chapter08/03-HashCollisionSeparateChaining.html b/examples/chapter08/03-HashCollisionSeparateChaining.html new file mode 100755 index 00000000..cddcc3db --- /dev/null +++ b/examples/chapter08/03-HashCollisionSeparateChaining.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter08/03-HashCollisionSeparateChaining.js b/examples/chapter08/03-HashCollisionSeparateChaining.js new file mode 100755 index 00000000..f791ba89 --- /dev/null +++ b/examples/chapter08/03-HashCollisionSeparateChaining.js @@ -0,0 +1,46 @@ +const { HashTableSeparateChaining } = PacktDataStructuresAlgorithms; + +const hashTable = new HashTableSeparateChaining(); + +hashTable.put('Ygritte', 'ygritte@email.com'); +hashTable.put('Jonathan', 'jonathan@email.com'); +hashTable.put('Jamie', 'jamie@email.com'); +hashTable.put('Jack', 'jack@email.com'); +hashTable.put('Jasmine', 'jasmine@email.com'); +hashTable.put('Jake', 'jake@email.com'); +hashTable.put('Nathan', 'nathan@email.com'); +hashTable.put('Athelstan', 'athelstan@email.com'); +hashTable.put('Sue', 'sue@email.com'); +hashTable.put('Aethelwulf', 'aethelwulf@email.com'); +hashTable.put('Sargeras', 'sargeras@email.com'); + +console.log('**** Printing Hash **** '); + +console.log(hashTable.toString()); +// {4 => [#Ygritte: ygritte@email.com]},{5 => [#Jonathan: jonathan@email.com],[#Jamie: jamie@email.com],[#Sue: sue@email.com],[#Aethelwulf: aethelwulf@email.com]},{7 => [#Jack: jack@email.com],[#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com],[#Sargeras: sargeras@email.com]} + +console.log('**** Get **** '); + +console.log(hashTable.get('Jamie')); // jamie@email.com +console.log(hashTable.get('Sue')); // sue@email.com +console.log(hashTable.get('Jonathan')); // jonathan@email.com +console.log(hashTable.get('Loiane')); // undefined + +console.log('**** Remove **** '); + +console.log(hashTable.remove('Ygritte')); // true +console.log(hashTable.get('Ygritte')); // undefined +console.log(hashTable.toString()); +// {5 => [#Jonathan: jonathan@email.com],[#Jamie: jamie@email.com],[#Sue: sue@email.com],[#Aethelwulf: aethelwulf@email.com]},{7 => [#Jack: jack@email.com],[#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com],[#Sargeras: sargeras@email.com]} + +console.log(hashTable.remove('Sue')); // true +console.log(hashTable.toString()); +// {5 => [#Jonathan: jonathan@email.com],[#Jamie: jamie@email.com],[#Aethelwulf: aethelwulf@email.com]},{7 => [#Jack: jack@email.com],[#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com],[#Sargeras: sargeras@email.com]} + +console.log(hashTable.remove('Jamie')); // true +console.log(hashTable.toString()); +// {5 => [#Jonathan: jonathan@email.com],[#Aethelwulf: aethelwulf@email.com]},{7 => [#Jack: jack@email.com],[#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com],[#Sargeras: sargeras@email.com]} + +console.log(hashTable.remove('Aethelwulf')); // true +console.log(hashTable.toString()); +// {5 => [#Jonathan: jonathan@email.com]},{7 => [#Jack: jack@email.com],[#Athelstan: athelstan@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com],[#Sargeras: sargeras@email.com]} diff --git a/examples/chapter08/04-HashCollisionLinearProbing.html b/examples/chapter08/04-HashCollisionLinearProbing.html new file mode 100755 index 00000000..6f8bbe52 --- /dev/null +++ b/examples/chapter08/04-HashCollisionLinearProbing.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter08/04-HashCollisionLinearProbing.js b/examples/chapter08/04-HashCollisionLinearProbing.js new file mode 100755 index 00000000..b75cd98d --- /dev/null +++ b/examples/chapter08/04-HashCollisionLinearProbing.js @@ -0,0 +1,42 @@ +const { HashTableLinearProbing } = PacktDataStructuresAlgorithms; + +const hashTable = new HashTableLinearProbing(); + +hashTable.put('Ygritte', 'ygritte@email.com'); +hashTable.put('Jonathan', 'jonathan@email.com'); +hashTable.put('Jamie', 'jamie@email.com'); +hashTable.put('Jack', 'jack@email.com'); +hashTable.put('Jasmine', 'jasmine@email.com'); +hashTable.put('Jake', 'jake@email.com'); +hashTable.put('Nathan', 'nathan@email.com'); +hashTable.put('Athelstan', 'athelstan@email.com'); +hashTable.put('Sue', 'sue@email.com'); +hashTable.put('Aethelwulf', 'aethelwulf@email.com'); +hashTable.put('Sargeras', 'sargeras@email.com'); + +console.log('**** Printing Hash **** '); + +console.log(hashTable.toString()); +// {4 => [#Ygritte: ygritte@email.com]},{5 => [#Jonathan: jonathan@email.com]},{6 => [#Jamie: jamie@email.com]},{7 => [#Jack: jack@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com]},{11 => [#Athelstan: athelstan@email.com]},{12 => [#Sue: sue@email.com]},{13 => [#Aethelwulf: aethelwulf@email.com]},{14 => [#Sargeras: sargeras@email.com]} +console.log('**** Get **** '); + +console.log(hashTable.get('Nathan')); // nathan@email.com +console.log(hashTable.get('Loiane')); // undefined + +console.log('**** Remove **** '); + +hashTable.remove('Ygritte'); +console.log(hashTable.get('Ygritte')); // undefined +console.log(hashTable.toString()); +// {5 => [#Jonathan: jonathan@email.com]},{6 => [#Jamie: jamie@email.com]},{7 => [#Jack: jack@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com]},{11 => [#Athelstan: athelstan@email.com]},{12 => [#Sue: sue@email.com]},{13 => [#Aethelwulf: aethelwulf@email.com]},{14 => [#Sargeras: sargeras@email.com]} + +console.log('**** Remove Test 2 **** '); +console.log('Removing Jonathan', hashTable.remove('Jonathan')); // true +console.log('**** Print **** '); +console.log(hashTable.toString()); +// {5 => [#Jamie: jamie@email.com]},{6 => [#Sue: sue@email.com]},{7 => [#Jack: jack@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com]},{11 => [#Athelstan: athelstan@email.com]},{12 => [#Aethelwulf: aethelwulf@email.com]},{13 => [#Sargeras: sargeras@email.com]} + +console.log(hashTable.get('Jamie')); // jamie@email.com +console.log('**** Print **** '); +console.log(hashTable.toString()); +// {5 => [#Jamie: jamie@email.com]},{6 => [#Sue: sue@email.com]},{7 => [#Jack: jack@email.com]},{8 => [#Jasmine: jasmine@email.com]},{9 => [#Jake: jake@email.com]},{10 => [#Nathan: nathan@email.com]},{11 => [#Athelstan: athelstan@email.com]},{12 => [#Aethelwulf: aethelwulf@email.com]},{13 => [#Sargeras: sargeras@email.com]} diff --git a/chapter07/10-ES6WeakMap.html b/examples/chapter08/05-ES2015Map.html old mode 100644 new mode 100755 similarity index 68% rename from chapter07/10-ES6WeakMap.html rename to examples/chapter08/05-ES2015Map.html index 25b28e2d..8a2ade05 --- a/chapter07/10-ES6WeakMap.html +++ b/examples/chapter08/05-ES2015Map.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter08/05-ES2015Map.js b/examples/chapter08/05-ES2015Map.js new file mode 100755 index 00000000..e944f988 --- /dev/null +++ b/examples/chapter08/05-ES2015Map.js @@ -0,0 +1,17 @@ +const map = new Map(); + +map.set('Gandalf', 'gandalf@email.com'); +map.set('John', 'johnsnow@email.com'); +map.set('Tyrion', 'tyrion@email.com'); + +console.log(map.has('Gandalf')); // true +console.log(map.size); // 3 + +console.log(map.keys()); // MapIterator {"Gandalf", "John", "Tyrion"} +console.log(map.values()); // MapIterator {"gandalf@email.com", "johnsnow@email.com", "tyrion@email.com"} +console.log(map.get('Tyrion')); // tyrion@email.com + +map.delete('John'); + +console.log(map.keys()); // MapIterator {"Gandalf", "Tyrion"} +console.log(map.values()); // MapIterator {"gandalf@email.com", "tyrion@email.com"} diff --git a/chapter07/09-ES6Map.html b/examples/chapter08/06-ES2015WeakMap.html old mode 100644 new mode 100755 similarity index 67% rename from chapter07/09-ES6Map.html rename to examples/chapter08/06-ES2015WeakMap.html index e755aac7..15daf46d --- a/chapter07/09-ES6Map.html +++ b/examples/chapter08/06-ES2015WeakMap.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter08/06-ES2015WeakMap.js b/examples/chapter08/06-ES2015WeakMap.js new file mode 100755 index 00000000..1f2d01bc --- /dev/null +++ b/examples/chapter08/06-ES2015WeakMap.js @@ -0,0 +1,18 @@ +const map = new WeakMap(); + +const ob1 = { name: 'Gandalf' }; +const ob2 = { name: 'John' }; +const ob3 = { name: 'Tyrion' }; + +map.set(ob1, 'gandalf@email.com'); +map.set(ob2, 'johnsnow@email.com'); +map.set(ob3, 'tyrion@email.com'); + +console.log(map.has(ob1)); // true +console.log(map.has(ob2)); // true +console.log(map.has(ob3)); // true + +console.log(map.get(ob3)); // tyrion@email.com + +map.delete(ob2); +console.log(map.has(ob2)); // false diff --git a/chapter07/11-ES6WeakSet.html b/examples/chapter08/07-ES2015WeakSet.html old mode 100644 new mode 100755 similarity index 67% rename from chapter07/11-ES6WeakSet.html rename to examples/chapter08/07-ES2015WeakSet.html index 68710e76..7a4f82f4 --- a/chapter07/11-ES6WeakSet.html +++ b/examples/chapter08/07-ES2015WeakSet.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter08/07-ES2015WeakSet.js b/examples/chapter08/07-ES2015WeakSet.js new file mode 100755 index 00000000..0e849f1a --- /dev/null +++ b/examples/chapter08/07-ES2015WeakSet.js @@ -0,0 +1,16 @@ +var set = new WeakSet(); + +const ob1 = { name: 'Gandalf' }; +const ob2 = { name: 'John' }; +const ob3 = { name: 'Tyrion' }; + +set.add(ob1); +set.add(ob2); +set.add(ob3); + +console.log(set.has(ob1)); // true +console.log(set.has(ob2)); // true +console.log(set.has(ob3)); // true + +set.delete(ob2); +console.log(set.has(ob2)); // false diff --git a/chapter03/01-Stack.html b/examples/chapter09/01-IntroRecursion.html old mode 100755 new mode 100644 similarity index 60% rename from chapter03/01-Stack.html rename to examples/chapter09/01-IntroRecursion.html index e936b4e1..ae42e54f --- a/chapter03/01-Stack.html +++ b/examples/chapter09/01-IntroRecursion.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter09/01-IntroRecursion.js b/examples/chapter09/01-IntroRecursion.js new file mode 100644 index 00000000..d2843215 --- /dev/null +++ b/examples/chapter09/01-IntroRecursion.js @@ -0,0 +1,26 @@ + +// functions commented below - inifite loop + +/* +function recursiveFunction(someParam) { + recursiveFunction(someParam); +} + +function recursiveFunction1(someParam) { + recursiveFunction2(someParam); +} + +function recursiveFunction2(someParam) { + recursiveFunction1(someParam); +} +*/ + +function understandRecursion(doIunderstandRecursion) { + const recursionAnswer = confirm('Do you understand recursion?'); // function logic + if (recursionAnswer === true) { // base case or stop point + return true; + } + understandRecursion(recursionAnswer); // recursive call +} + +understandRecursion(false); diff --git a/chapter04/01-Queue.html b/examples/chapter09/02-Factorial.html similarity index 60% rename from chapter04/01-Queue.html rename to examples/chapter09/02-Factorial.html index 4220c419..94c6c103 100755 --- a/chapter04/01-Queue.html +++ b/examples/chapter09/02-Factorial.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/examples/chapter09/02-Factorial.js b/examples/chapter09/02-Factorial.js new file mode 100644 index 00000000..774006f9 --- /dev/null +++ b/examples/chapter09/02-Factorial.js @@ -0,0 +1,26 @@ +// @ts-check + +function factorialIterative(number) { + if (number < 0) { + return undefined; + } + let total = 1; + for (let n = number; n > 1; n--) { + total = total * n; + } + return total; +} + +console.log('factorialIterative(5): ', factorialIterative(5)); +console.log('factorialIterative(3): ', factorialIterative(3)); + +function factorial(n) { + // console.trace(); + if (n === 1 || n === 0) { + return 1; + } + return n * factorial(n - 1); +} + +console.log('factorial(5): ', factorial(5)); +console.log('factorial(3): ', factorial(3)); diff --git a/examples/chapter09/03-JSCallStack.html b/examples/chapter09/03-JSCallStack.html new file mode 100644 index 00000000..0f88040d --- /dev/null +++ b/examples/chapter09/03-JSCallStack.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/chapter09/03-JSCallStack.js b/examples/chapter09/03-JSCallStack.js new file mode 100644 index 00000000..fcfd6ef8 --- /dev/null +++ b/examples/chapter09/03-JSCallStack.js @@ -0,0 +1,11 @@ +let i = 0; +function recursiveFn() { + i++; + recursiveFn(); +} + +try { + recursiveFn(); +} catch (ex) { + console.log('i = ' + i + ' error: ' + ex); +} diff --git a/examples/chapter09/04-Fibonacci.html b/examples/chapter09/04-Fibonacci.html new file mode 100755 index 00000000..8413c457 --- /dev/null +++ b/examples/chapter09/04-Fibonacci.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/chapter09/04-Fibonacci.js b/examples/chapter09/04-Fibonacci.js new file mode 100644 index 00000000..3b395774 --- /dev/null +++ b/examples/chapter09/04-Fibonacci.js @@ -0,0 +1,43 @@ +function fibonacci(n){ + if (n < 1) return 0; // {1} + if (n <= 2) return 1; // {2} + return fibonacci(n - 1) + fibonacci(n - 2); // {3} +} + +console.log('fibonacci(2)', fibonacci(2)); +console.log('fibonacci(3)', fibonacci(3)); +console.log('fibonacci(4)', fibonacci(4)); +console.log('fibonacci(5)', fibonacci(5)); + +function fibonacciIterative(n){ + let fibNMinus2 = 0; + let fibNMinus1 = 1; + let fibN = n; + for (let i = 2; i <= n; i++) { // n >= 2 + fibN = fibNMinus1 + fibNMinus2; // f(n-1) + f(n-2) + fibNMinus2 = fibNMinus1; + fibNMinus1 = fibN; + } + return fibN; +} + +console.log('fibonacciIterative(2)', fibonacciIterative(2)); +console.log('fibonacciIterative(3)', fibonacciIterative(3)); +console.log('fibonacciIterative(4)', fibonacciIterative(4)); +console.log('fibonacciIterative(5)', fibonacciIterative(5)); + +function fibonacciMemoization(n) { + const memo = [0, 1]; + const fibonacci = (n) => { + if (memo[n] != null) return memo[n]; + return memo[n] = fibonacci(n - 1, memo) + fibonacci(n - 2, memo); + }; + return fibonacci(n); +} + +console.log('fibonacciMemoization(2)', fibonacciMemoization(2)); +console.log('fibonacciMemoization(3)', fibonacciMemoization(3)); +console.log('fibonacciMemoization(4)', fibonacciMemoization(4)); +console.log('fibonacciMemoization(5)', fibonacciMemoization(5)); + +// https://jsperf.com/fibonacci-comparison-jsbook diff --git a/examples/chapter10/01-UsingMinHeap.html b/examples/chapter10/01-UsingMinHeap.html new file mode 100644 index 00000000..83814ba1 --- /dev/null +++ b/examples/chapter10/01-UsingMinHeap.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter10/01-UsingMinHeap.js b/examples/chapter10/01-UsingMinHeap.js new file mode 100644 index 00000000..59b7753b --- /dev/null +++ b/examples/chapter10/01-UsingMinHeap.js @@ -0,0 +1,27 @@ +const { MinHeap } = PacktDataStructuresAlgorithms; + +let heap = new MinHeap(); + +heap.insert(2); +heap.insert(3); +heap.insert(4); +heap.insert(5); + +heap.insert(2); + +console.log(heap.getAsArray()); + +console.log('Heap size: ', heap.size()); // 5 +console.log('Heap is empty: ', heap.isEmpty()); // false +console.log('Heap min value: ', heap.findMinimum()); // 1 + +heap = new MinHeap(); +for (let i = 1; i < 10; i++) { + heap.insert(i); +} + +console.log(heap.getAsArray()); + +console.log('Extract minimum: ', heap.extract()); // 1 +console.log(heap.getAsArray()); // [2, 4, 3, 8, 5, 6, 7, 9] + diff --git a/examples/chapter10/02-UsingMaxHeap.html b/examples/chapter10/02-UsingMaxHeap.html new file mode 100644 index 00000000..9d573bda --- /dev/null +++ b/examples/chapter10/02-UsingMaxHeap.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter10/02-UsingMaxHeap.js b/examples/chapter10/02-UsingMaxHeap.js new file mode 100644 index 00000000..f1a5b97d --- /dev/null +++ b/examples/chapter10/02-UsingMaxHeap.js @@ -0,0 +1,27 @@ +const { MaxHeap } = PacktDataStructuresAlgorithms; + +const maxHeap = new MaxHeap(); + +maxHeap.insert(2); +maxHeap.insert(3); +maxHeap.insert(4); +maxHeap.insert(5); + +maxHeap.insert(1); + +console.log(maxHeap.getAsArray()); + +console.log('Heap size: ', maxHeap.size()); // 5 +console.log('Heap is empty: ', maxHeap.isEmpty()); // false +console.log('Heap min value: ', maxHeap.findMinimum()); // 5 + +maxHeap.insert(6); +maxHeap.insert(9); +maxHeap.insert(10); +maxHeap.insert(14); + +console.log(maxHeap.getAsArray()); + +console.log('Extract minimum: ', maxHeap.extract()); +console.log(maxHeap.getAsArray()); + diff --git a/examples/chapter10/03-HeapSort.html b/examples/chapter10/03-HeapSort.html new file mode 100644 index 00000000..e52c43f4 --- /dev/null +++ b/examples/chapter10/03-HeapSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter10/03-HeapSort.js b/examples/chapter10/03-HeapSort.js new file mode 100644 index 00000000..9d9b1ac0 --- /dev/null +++ b/examples/chapter10/03-HeapSort.js @@ -0,0 +1,7 @@ +const { heapSort } = PacktDataStructuresAlgorithms; + +console.log('********** Heap Sort **********'); +const array = [7, 6, 3, 5, 4, 1, 2]; + +console.log('Before sorting: ', array); +console.log('After sorting: ', heapSort(array)); diff --git a/examples/chapter11/01-UsingMinHeap.html b/examples/chapter11/01-UsingMinHeap.html new file mode 100644 index 00000000..83814ba1 --- /dev/null +++ b/examples/chapter11/01-UsingMinHeap.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter11/01-UsingMinHeap.js b/examples/chapter11/01-UsingMinHeap.js new file mode 100644 index 00000000..59b7753b --- /dev/null +++ b/examples/chapter11/01-UsingMinHeap.js @@ -0,0 +1,27 @@ +const { MinHeap } = PacktDataStructuresAlgorithms; + +let heap = new MinHeap(); + +heap.insert(2); +heap.insert(3); +heap.insert(4); +heap.insert(5); + +heap.insert(2); + +console.log(heap.getAsArray()); + +console.log('Heap size: ', heap.size()); // 5 +console.log('Heap is empty: ', heap.isEmpty()); // false +console.log('Heap min value: ', heap.findMinimum()); // 1 + +heap = new MinHeap(); +for (let i = 1; i < 10; i++) { + heap.insert(i); +} + +console.log(heap.getAsArray()); + +console.log('Extract minimum: ', heap.extract()); // 1 +console.log(heap.getAsArray()); // [2, 4, 3, 8, 5, 6, 7, 9] + diff --git a/examples/chapter11/02-UsingMaxHeap.html b/examples/chapter11/02-UsingMaxHeap.html new file mode 100644 index 00000000..9d573bda --- /dev/null +++ b/examples/chapter11/02-UsingMaxHeap.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter11/02-UsingMaxHeap.js b/examples/chapter11/02-UsingMaxHeap.js new file mode 100644 index 00000000..f1a5b97d --- /dev/null +++ b/examples/chapter11/02-UsingMaxHeap.js @@ -0,0 +1,27 @@ +const { MaxHeap } = PacktDataStructuresAlgorithms; + +const maxHeap = new MaxHeap(); + +maxHeap.insert(2); +maxHeap.insert(3); +maxHeap.insert(4); +maxHeap.insert(5); + +maxHeap.insert(1); + +console.log(maxHeap.getAsArray()); + +console.log('Heap size: ', maxHeap.size()); // 5 +console.log('Heap is empty: ', maxHeap.isEmpty()); // false +console.log('Heap min value: ', maxHeap.findMinimum()); // 5 + +maxHeap.insert(6); +maxHeap.insert(9); +maxHeap.insert(10); +maxHeap.insert(14); + +console.log(maxHeap.getAsArray()); + +console.log('Extract minimum: ', maxHeap.extract()); +console.log(maxHeap.getAsArray()); + diff --git a/examples/chapter11/03-HeapSort.html b/examples/chapter11/03-HeapSort.html new file mode 100644 index 00000000..e52c43f4 --- /dev/null +++ b/examples/chapter11/03-HeapSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter11/03-HeapSort.js b/examples/chapter11/03-HeapSort.js new file mode 100644 index 00000000..9d9b1ac0 --- /dev/null +++ b/examples/chapter11/03-HeapSort.js @@ -0,0 +1,7 @@ +const { heapSort } = PacktDataStructuresAlgorithms; + +console.log('********** Heap Sort **********'); +const array = [7, 6, 3, 5, 4, 1, 2]; + +console.log('Before sorting: ', array); +console.log('After sorting: ', heapSort(array)); diff --git a/examples/chapter12/01-UsingGraphs.html b/examples/chapter12/01-UsingGraphs.html new file mode 100644 index 00000000..49eb9bff --- /dev/null +++ b/examples/chapter12/01-UsingGraphs.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/01-UsingGraphs.js b/examples/chapter12/01-UsingGraphs.js new file mode 100644 index 00000000..dde70c0d --- /dev/null +++ b/examples/chapter12/01-UsingGraphs.js @@ -0,0 +1,23 @@ +const { Graph } = PacktDataStructuresAlgorithms; + +const graph = new Graph(); + +const myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + +for (let i = 0; i < myVertices.length; i++) { + graph.addVertex(myVertices[i]); +} +graph.addEdge('A', 'B'); +graph.addEdge('A', 'C'); +graph.addEdge('A', 'D'); +graph.addEdge('C', 'D'); +graph.addEdge('C', 'G'); +graph.addEdge('D', 'G'); +graph.addEdge('D', 'H'); +graph.addEdge('B', 'E'); +graph.addEdge('B', 'F'); +graph.addEdge('E', 'I'); + +console.log('********* printing graph ***********'); + +console.log(graph.toString()); diff --git a/examples/chapter12/02-BFS.html b/examples/chapter12/02-BFS.html new file mode 100644 index 00000000..044da5d6 --- /dev/null +++ b/examples/chapter12/02-BFS.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/02-BFS.js b/examples/chapter12/02-BFS.js new file mode 100644 index 00000000..d65c8b66 --- /dev/null +++ b/examples/chapter12/02-BFS.js @@ -0,0 +1,54 @@ +const { Graph } = PacktDataStructuresAlgorithms; +const { Stack } = PacktDataStructuresAlgorithms; +const { BFS } = PacktDataStructuresAlgorithms; +const { breadthFirstSearch } = PacktDataStructuresAlgorithms; + +const graph = new Graph(); + +const myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + +for (let i = 0; i < myVertices.length; i++) { + graph.addVertex(myVertices[i]); +} +graph.addEdge('A', 'B'); +graph.addEdge('A', 'C'); +graph.addEdge('A', 'D'); +graph.addEdge('C', 'D'); +graph.addEdge('C', 'G'); +graph.addEdge('D', 'G'); +graph.addEdge('D', 'H'); +graph.addEdge('B', 'E'); +graph.addEdge('B', 'F'); +graph.addEdge('E', 'I'); + +console.log('********* printing graph ***********'); + +console.log(graph.toString()); + +console.log('********* bfs with callback ***********'); + +const printVertex = (value) => console.log('Visited vertex: ' + value); + +breadthFirstSearch(graph, myVertices[0], printVertex); + +console.log('********* sorthest path - BFS ***********'); +const shortestPathA = BFS(graph, myVertices[0]); +console.log(shortestPathA.distances); +console.log(shortestPathA.predecessors); + +//from A to all other vertices +const fromVertex = myVertices[0]; + +for (let i = 1; i < myVertices.length; i++) { + const toVertex = myVertices[i]; + const path = new Stack(); + for (let v = toVertex; v !== fromVertex; v = shortestPathA.predecessors[v]) { + path.push(v); + } + path.push(fromVertex); + let s = path.pop(); + while (!path.isEmpty()) { + s += ' - ' + path.pop(); + } + console.log(s); +} diff --git a/examples/chapter12/03-DFS.html b/examples/chapter12/03-DFS.html new file mode 100644 index 00000000..1a5bd4f3 --- /dev/null +++ b/examples/chapter12/03-DFS.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/03-DFS.js b/examples/chapter12/03-DFS.js new file mode 100644 index 00000000..5c440a74 --- /dev/null +++ b/examples/chapter12/03-DFS.js @@ -0,0 +1,67 @@ +const { Graph } = PacktDataStructuresAlgorithms; +const { depthFirstSearch } = PacktDataStructuresAlgorithms; +const { DFS } = PacktDataStructuresAlgorithms; + +let graph = new Graph(true); + +let myVertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + +for (let i = 0; i < myVertices.length; i++) { + graph.addVertex(myVertices[i]); +} +graph.addEdge('A', 'B'); +graph.addEdge('A', 'C'); +graph.addEdge('A', 'D'); +graph.addEdge('C', 'D'); +graph.addEdge('C', 'G'); +graph.addEdge('D', 'G'); +graph.addEdge('D', 'H'); +graph.addEdge('B', 'E'); +graph.addEdge('B', 'F'); +graph.addEdge('E', 'I'); + +console.log('********* printing graph ***********'); + +console.log(graph.toString()); + +console.log('********* dfs with callback ***********'); + +const printVertex = value => console.log('Visited vertex: ' + value); + +depthFirstSearch(graph, printVertex); + +console.log('********* topological sort - DFS ***********'); + +graph = new Graph(true); // directed graph + +myVertices = ['A', 'B', 'C', 'D', 'E', 'F']; +for (i = 0; i < myVertices.length; i++) { + graph.addVertex(myVertices[i]); +} +graph.addEdge('A', 'C'); +graph.addEdge('A', 'D'); +graph.addEdge('B', 'D'); +graph.addEdge('B', 'E'); +graph.addEdge('C', 'F'); +graph.addEdge('F', 'E'); + +const result = DFS(graph); +console.log('discovery', result.discovery); +console.log('finished', result.finished); +console.log('predecessors', result.predecessors); + +const fTimes = result.finished; +s = ''; +for (let count = 0; count < myVertices.length; count++) { + let max = 0; + let maxName = null; + for (i = 0; i < myVertices.length; i++) { + if (fTimes[myVertices[i]] > max) { + max = fTimes[myVertices[i]]; + maxName = myVertices[i]; + } + } + s += ' - ' + maxName; + delete fTimes[maxName]; +} +console.log(s); diff --git a/examples/chapter12/04-Dijkstra.html b/examples/chapter12/04-Dijkstra.html new file mode 100644 index 00000000..8b9e0f74 --- /dev/null +++ b/examples/chapter12/04-Dijkstra.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/04-Dijkstra.js b/examples/chapter12/04-Dijkstra.js new file mode 100644 index 00000000..dfa58854 --- /dev/null +++ b/examples/chapter12/04-Dijkstra.js @@ -0,0 +1,18 @@ +const { dijkstra } = PacktDataStructuresAlgorithms; + +const graph = [ + [0, 2, 4, 0, 0, 0], + [0, 0, 2, 4, 2, 0], + [0, 0, 0, 0, 3, 0], + [0, 0, 0, 0, 0, 2], + [0, 0, 0, 3, 0, 2], + [0, 0, 0, 0, 0, 0] +]; + +console.log("********* Dijkstra's Algorithm - Shortest Path ***********"); + +const dist = dijkstra(graph, 0); + +for (i = 0; i < dist.length; i++){ + console.log(i + '\t\t' + dist[i]); +} diff --git a/examples/chapter12/05-Floyd-Warshall.html b/examples/chapter12/05-Floyd-Warshall.html new file mode 100644 index 00000000..be411625 --- /dev/null +++ b/examples/chapter12/05-Floyd-Warshall.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/05-Floyd-Warshall.js b/examples/chapter12/05-Floyd-Warshall.js new file mode 100644 index 00000000..18c2dee6 --- /dev/null +++ b/examples/chapter12/05-Floyd-Warshall.js @@ -0,0 +1,25 @@ +const { floydWarshall } = PacktDataStructuresAlgorithms; + +const INF = Infinity; +const graph = [ + [INF, 2, 4, INF, INF, INF], + [INF, INF, 2, 4, 2, INF], + [INF, INF, INF, INF, 3, INF], + [INF, INF, INF, INF, INF, 2], + [INF, INF, INF, 3, INF, 2], + [INF, INF, INF, INF, INF, INF] +]; + +console.log('********* Floyd-Warshall Algorithm - All-Pairs Shortest Path ***********'); + +dist = floydWarshall(graph); + +let s = ''; +for (let i = 0; i < dist.length; ++i) { + s = ''; + for (var j = 0; j < dist.length; ++j) { + if (dist[i][j] === INF) s += 'INF '; + else s += dist[i][j] + ' '; + } + console.log(s); +} diff --git a/examples/chapter12/06-Prim.html b/examples/chapter12/06-Prim.html new file mode 100644 index 00000000..7cbb2537 --- /dev/null +++ b/examples/chapter12/06-Prim.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/06-Prim.js b/examples/chapter12/06-Prim.js new file mode 100644 index 00000000..cb971a4e --- /dev/null +++ b/examples/chapter12/06-Prim.js @@ -0,0 +1,19 @@ +const { prim } = PacktDataStructuresAlgorithms; + +const graph = [ + [0, 2, 4, 0, 0, 0], + [2, 0, 2, 4, 2, 0], + [4, 2, 0, 0, 3, 0], + [0, 4, 0, 0, 3, 2], + [0, 2, 3, 3, 0, 2], + [0, 0, 0, 2, 2, 0] +]; + +console.log("********* Prim's Algorithm - Minimum Spanning Tree ***********"); + +const parent = prim(graph); + +console.log('Edge Weight'); +for (let i = 1; i < graph.length; i++) { + console.log(parent[i] + ' - ' + i + ' ' + graph[i][parent[i]]); +} diff --git a/examples/chapter12/07-Kruskal.html b/examples/chapter12/07-Kruskal.html new file mode 100644 index 00000000..89e214fb --- /dev/null +++ b/examples/chapter12/07-Kruskal.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter12/07-Kruskal.js b/examples/chapter12/07-Kruskal.js new file mode 100644 index 00000000..460fbd83 --- /dev/null +++ b/examples/chapter12/07-Kruskal.js @@ -0,0 +1,19 @@ +const { kruskal } = PacktDataStructuresAlgorithms; + +const graph = [ + [0, 2, 4, 0, 0, 0], + [2, 0, 2, 4, 2, 0], + [4, 2, 0, 0, 3, 0], + [0, 4, 0, 0, 3, 2], + [0, 2, 3, 3, 0, 2], + [0, 0, 0, 2, 2, 0] +]; + +console.log('********* Kruskal Algorithm - Minimum Spanning Tree ***********'); + +const parent = kruskal(graph); + +console.log('Edge Weight'); +for (i = 1; i < graph.length; i++) { + console.log(parent[i] + ' - ' + i + ' ' + graph[i][parent[i]]); +} diff --git a/examples/chapter13/01-BubbleSort.html b/examples/chapter13/01-BubbleSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-BubbleSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-BubbleSort.js b/examples/chapter13/01-BubbleSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-BubbleSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-BucketSort.html b/examples/chapter13/01-BucketSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-BucketSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-BucketSort.js b/examples/chapter13/01-BucketSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-BucketSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-CountingSort.html b/examples/chapter13/01-CountingSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-CountingSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-CountingSort.js b/examples/chapter13/01-CountingSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-CountingSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-InsertionSort.html b/examples/chapter13/01-InsertionSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-InsertionSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-InsertionSort.js b/examples/chapter13/01-InsertionSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-InsertionSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-MergeSort.html b/examples/chapter13/01-MergeSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-MergeSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-MergeSort.js b/examples/chapter13/01-MergeSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-MergeSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-QuickSort.html b/examples/chapter13/01-QuickSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-QuickSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-QuickSort.js b/examples/chapter13/01-QuickSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-QuickSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-RadixSort.html b/examples/chapter13/01-RadixSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-RadixSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-RadixSort.js b/examples/chapter13/01-RadixSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-RadixSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter13/01-SelectionSort.html b/examples/chapter13/01-SelectionSort.html new file mode 100644 index 00000000..88d9a1da --- /dev/null +++ b/examples/chapter13/01-SelectionSort.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter13/01-SelectionSort.js b/examples/chapter13/01-SelectionSort.js new file mode 100644 index 00000000..fff8970e --- /dev/null +++ b/examples/chapter13/01-SelectionSort.js @@ -0,0 +1,12 @@ +const { bubbleSort } = PacktDataStructuresAlgorithms; + +function createNonSortedArray(){ + var array = []; + for (let i = 5; i > 0; i--){ + array.push(i); + } + return array; +} + +const array = bubbleSort(createNonSortedArray()); +console.log(array); diff --git a/examples/chapter14/01-DC-BinarySearch.html b/examples/chapter14/01-DC-BinarySearch.html new file mode 100644 index 00000000..b110b636 --- /dev/null +++ b/examples/chapter14/01-DC-BinarySearch.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/01-DC-BinarySearch.js b/examples/chapter14/01-DC-BinarySearch.js new file mode 100644 index 00000000..e69de29b diff --git a/examples/chapter14/02-MinCoinChangeDP.html b/examples/chapter14/02-MinCoinChangeDP.html new file mode 100644 index 00000000..4c2027b3 --- /dev/null +++ b/examples/chapter14/02-MinCoinChangeDP.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/02-MinCoinChangeDP.js b/examples/chapter14/02-MinCoinChangeDP.js new file mode 100644 index 00000000..51ce7ed3 --- /dev/null +++ b/examples/chapter14/02-MinCoinChangeDP.js @@ -0,0 +1,5 @@ +const { minCoinChange } = PacktDataStructuresAlgorithms; + +console.log(minCoinChange([1, 5, 10], 15)); // [5, 10] +console.log(minCoinChange([1, 3, 4], 6)); // [3, 3] + diff --git a/examples/chapter14/03-MinCoinChangeGreedy.html b/examples/chapter14/03-MinCoinChangeGreedy.html new file mode 100644 index 00000000..92b0618f --- /dev/null +++ b/examples/chapter14/03-MinCoinChangeGreedy.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/03-MinCoinChangeGreedy.js b/examples/chapter14/03-MinCoinChangeGreedy.js new file mode 100644 index 00000000..584603f2 --- /dev/null +++ b/examples/chapter14/03-MinCoinChangeGreedy.js @@ -0,0 +1,5 @@ +const { minCoinChangeGreedy } = PacktDataStructuresAlgorithms; + +console.log(minCoinChangeGreedy([1, 5, 10], 15)); // [5, 10] +console.log(minCoinChangeGreedy([1, 3, 4], 6)); // [4, 1, 1] + diff --git a/examples/chapter14/04-KnapsackProblemDP.html b/examples/chapter14/04-KnapsackProblemDP.html new file mode 100644 index 00000000..1f06c983 --- /dev/null +++ b/examples/chapter14/04-KnapsackProblemDP.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/04-KnapsackProblemDP.js b/examples/chapter14/04-KnapsackProblemDP.js new file mode 100644 index 00000000..e9ff4369 --- /dev/null +++ b/examples/chapter14/04-KnapsackProblemDP.js @@ -0,0 +1,8 @@ +const { knapSack } = PacktDataStructuresAlgorithms; + +const values = [3,4,5]; +const weights = [2,3,4]; +const capacity = 5; +const n = values.length; + +console.log(knapSack(capacity, weights, values, n)); diff --git a/examples/chapter14/05-KnapSackProblemRecursive.html b/examples/chapter14/05-KnapSackProblemRecursive.html new file mode 100644 index 00000000..610d7310 --- /dev/null +++ b/examples/chapter14/05-KnapSackProblemRecursive.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/05-KnapSackProblemRecursive.js b/examples/chapter14/05-KnapSackProblemRecursive.js new file mode 100644 index 00000000..ba76971b --- /dev/null +++ b/examples/chapter14/05-KnapSackProblemRecursive.js @@ -0,0 +1,8 @@ +const { knapSackRecursive } = PacktDataStructuresAlgorithms; + +const values = [3,4,5]; +const weights = [2,3,4]; +const capacity = 5; +const n = values.length; + +console.log(knapSackRecursive(capacity, weights, values, n)); diff --git a/examples/chapter14/06-KnapSackProblemGreedy.html b/examples/chapter14/06-KnapSackProblemGreedy.html new file mode 100644 index 00000000..0d2e3c04 --- /dev/null +++ b/examples/chapter14/06-KnapSackProblemGreedy.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/06-KnapSackProblemGreedy.js b/examples/chapter14/06-KnapSackProblemGreedy.js new file mode 100644 index 00000000..d9858107 --- /dev/null +++ b/examples/chapter14/06-KnapSackProblemGreedy.js @@ -0,0 +1,7 @@ +const { knapSackGreedy } = PacktDataStructuresAlgorithms; + +const values = [3,4,5]; +const weights = [2,3,4]; +const capacity = 5; + +console.log(knapSackGreedy(capacity, weights, values)); diff --git a/examples/chapter14/07-LongestCommonSubsequenceDP.html b/examples/chapter14/07-LongestCommonSubsequenceDP.html new file mode 100644 index 00000000..f4b8b8a8 --- /dev/null +++ b/examples/chapter14/07-LongestCommonSubsequenceDP.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/07-LongestCommonSubsequenceDP.js b/examples/chapter14/07-LongestCommonSubsequenceDP.js new file mode 100644 index 00000000..75e86015 --- /dev/null +++ b/examples/chapter14/07-LongestCommonSubsequenceDP.js @@ -0,0 +1,8 @@ +const { lcs } = PacktDataStructuresAlgorithms; +const { lcsPrint } = PacktDataStructuresAlgorithms; + +const wordX = 'acbaed'; +const wordY = 'abcadf'; + +console.log('lcs', lcs(wordX, wordY)); +console.log('lcsPrint', lcsPrint(wordX, wordY)); diff --git a/examples/chapter14/08-LongestCommonSubsequenceRecursive.html b/examples/chapter14/08-LongestCommonSubsequenceRecursive.html new file mode 100644 index 00000000..25fa3a3f --- /dev/null +++ b/examples/chapter14/08-LongestCommonSubsequenceRecursive.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/08-LongestCommonSubsequenceRecursive.js b/examples/chapter14/08-LongestCommonSubsequenceRecursive.js new file mode 100644 index 00000000..63c2daf7 --- /dev/null +++ b/examples/chapter14/08-LongestCommonSubsequenceRecursive.js @@ -0,0 +1,6 @@ +const { lcsRecursive } = PacktDataStructuresAlgorithms; + +const wordX = 'acbaed'; +const wordY = 'abcadf'; + +console.log('lcsRecursive', lcsRecursive(wordX, wordY)); diff --git a/examples/chapter14/09-MatrixChainMultiplicationDP.html b/examples/chapter14/09-MatrixChainMultiplicationDP.html new file mode 100644 index 00000000..110165d7 --- /dev/null +++ b/examples/chapter14/09-MatrixChainMultiplicationDP.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/09-MatrixChainMultiplicationDP.js b/examples/chapter14/09-MatrixChainMultiplicationDP.js new file mode 100644 index 00000000..50e92fd5 --- /dev/null +++ b/examples/chapter14/09-MatrixChainMultiplicationDP.js @@ -0,0 +1,4 @@ +const { matrixChainOrder } = PacktDataStructuresAlgorithms; + +const p = [10, 100, 5, 50, 1]; +console.log(matrixChainOrder(p)); diff --git a/examples/chapter14/10-MatrixChainMultiplicationRecursive.html b/examples/chapter14/10-MatrixChainMultiplicationRecursive.html new file mode 100644 index 00000000..eba9ceaf --- /dev/null +++ b/examples/chapter14/10-MatrixChainMultiplicationRecursive.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/10-MatrixChainMultiplicationRecursive.js b/examples/chapter14/10-MatrixChainMultiplicationRecursive.js new file mode 100644 index 00000000..97245276 --- /dev/null +++ b/examples/chapter14/10-MatrixChainMultiplicationRecursive.js @@ -0,0 +1,4 @@ +const { matrixChainOrderGreedy } = PacktDataStructuresAlgorithms; + +const p = [10, 100, 5, 50, 1]; +console.log(matrixChainOrderGreedy(p)); diff --git a/examples/chapter14/11-RatInMaze.html b/examples/chapter14/11-RatInMaze.html new file mode 100644 index 00000000..da73582f --- /dev/null +++ b/examples/chapter14/11-RatInMaze.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/11-RatInMaze.js b/examples/chapter14/11-RatInMaze.js new file mode 100644 index 00000000..221e7f19 --- /dev/null +++ b/examples/chapter14/11-RatInMaze.js @@ -0,0 +1,10 @@ +const { ratInAMaze } = PacktDataStructuresAlgorithms; + +const maze = [ + [1, 0, 0, 0], + [1, 1, 1, 1], + [0, 0, 1, 0], + [0, 1, 1, 1] +]; + +console.log(ratInAMaze(maze)); diff --git a/examples/chapter14/12-SudokuSolver.html b/examples/chapter14/12-SudokuSolver.html new file mode 100644 index 00000000..b3126287 --- /dev/null +++ b/examples/chapter14/12-SudokuSolver.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/examples/chapter14/12-SudokuSolver.js b/examples/chapter14/12-SudokuSolver.js new file mode 100644 index 00000000..bf52ddf3 --- /dev/null +++ b/examples/chapter14/12-SudokuSolver.js @@ -0,0 +1,15 @@ +const { sudokuSolver } = PacktDataStructuresAlgorithms; + +const sudokuGrid = [ + [5, 3, 0, 0, 7, 0, 0, 0, 0], + [6, 0, 0, 1, 9, 5, 0, 0, 0], + [0, 9, 8, 0, 0, 0, 0, 6, 0], + [8, 0, 0, 0, 6, 0, 0, 0, 3], + [4, 0, 0, 8, 0, 3, 0, 0, 1], + [7, 0, 0, 0, 2, 0, 0, 0, 6], + [0, 6, 0, 0, 0, 0, 2, 8, 0], + [0, 0, 0, 4, 1, 9, 0, 0, 5], + [0, 0, 0, 0, 8, 0, 0, 7, 9] +]; + +console.log(sudokuSolver(sudokuGrid)); diff --git a/examples/chapter14/13-IntroFunctionalProgramming.html b/examples/chapter14/13-IntroFunctionalProgramming.html new file mode 100644 index 00000000..0d7cd0ed --- /dev/null +++ b/examples/chapter14/13-IntroFunctionalProgramming.html @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/chapter11/12-IntroFunctionalProgramming.js b/examples/chapter14/13-IntroFunctionalProgramming.js similarity index 98% rename from chapter11/12-IntroFunctionalProgramming.js rename to examples/chapter14/13-IntroFunctionalProgramming.js index 47787255..692bebd6 100644 --- a/chapter11/12-IntroFunctionalProgramming.js +++ b/examples/chapter14/13-IntroFunctionalProgramming.js @@ -144,4 +144,4 @@ var positiveNumbers = function(array){ return num >= 0; }) }; -console.log(positiveNumbers([-1,1,2,-2])); \ No newline at end of file +console.log(positiveNumbers([-1,1,2,-2])); diff --git a/chapter12/05-BigONotation.html b/examples/chapter15/01-BigONotation.html old mode 100644 new mode 100755 similarity index 58% rename from chapter12/05-BigONotation.html rename to examples/chapter15/01-BigONotation.html index 317a5bfb..f8f26334 --- a/chapter12/05-BigONotation.html +++ b/examples/chapter15/01-BigONotation.html @@ -5,6 +5,6 @@ - + - \ No newline at end of file + diff --git a/chapter12/05-BigONotation.js b/examples/chapter15/01-BigONotation.js old mode 100644 new mode 100755 similarity index 100% rename from chapter12/05-BigONotation.js rename to examples/chapter15/01-BigONotation.js diff --git a/chapter12/bigOChart/chart.js b/examples/chapter15/bigOChart/chart.js old mode 100644 new mode 100755 similarity index 100% rename from chapter12/bigOChart/chart.js rename to examples/chapter15/bigOChart/chart.js diff --git a/chapter12/bigOChart/index.html b/examples/chapter15/bigOChart/index.html old mode 100644 new mode 100755 similarity index 100% rename from chapter12/bigOChart/index.html rename to examples/chapter15/bigOChart/index.html diff --git a/examples/examples-screenshot.png b/examples/examples-screenshot.png new file mode 100644 index 00000000..a264d142 Binary files /dev/null and b/examples/examples-screenshot.png differ diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 00000000..7e3e6629 --- /dev/null +++ b/examples/index.html @@ -0,0 +1,294 @@ + + + + + + Data Structures and Algorithms with JavaScript + + + + + + + + + + +
+
+
+ + Learning JavaScript Data Structures and Algorithms +
+ +
+ 01_02 + 03 + 04 + 05 + 06 + 07 + 08 + 09 + 10 + 11 + 12 + 13 + 14 + 15 +
+
+
+ Please open the Developer Tools Console to see the output + +
+ +
+ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+
+ + + diff --git a/firebase.json b/firebase.json new file mode 100644 index 00000000..f90fd865 --- /dev/null +++ b/firebase.json @@ -0,0 +1,11 @@ +{ + "hosting": { + "public": "examples", + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 00000000..49805359 --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "target": "ES5", + "module": "commonjs" , + "outDir": "./dist/js", + "removeComments": true, + "strict": true + }, + "exclude": ["node_modules", "dist"], + "include": ["src/js/**/*","html/**"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..3eefb3e9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,11344 @@ +{ + "name": "javascript-datastructures-algorithms", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", + "integrity": "sha512-DB+6rafIdc9o72Yc3/Ph5h+6hUjeOp66pF0naQBgUFFuPqzQwIlPTm3xZR7YNvduIMtkDIj2t21LSQwnbCrXvg==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + } + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.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" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.12.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.3.tgz", + "integrity": "sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.1.tgz", + "integrity": "sha512-MA3WPoRt1ZHo2ZmoGKNqi20YnPt0B1S0GTZEPhhd+hw2KGUzBlHuVunj6K4sNuK+reEvyiPwtp0cpaqLzJDmAw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.1", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.1", + "@babel/types": "^7.12.1", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.1.tgz", + "integrity": "sha512-BzSY3NJBKM4kyatSOWh3D/JJ2O3CVzBybHWxtgxnggaxEuaSTTDqeiSb/xk9lrkw2Tbqyivw5ZU4rT+EfznQsA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "dev": true + }, + "@types/chai": { + "version": "4.2.14", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.14.tgz", + "integrity": "sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ==", + "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 + }, + "@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 + }, + "@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "dev": true + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "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 + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" + } + }, + "append-transform": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-0.4.0.tgz", + "integrity": "sha1-126/jKlNJ24keja61EpLdKthGZE=", + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "argv": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", + "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "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.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": 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" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "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": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true, + "optional": 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 + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "chokidar": "^1.6.1", + "commander": "^2.11.0", + "convert-source-map": "^1.5.0", + "fs-readdir-recursive": "^1.0.0", + "glob": "^7.1.2", + "lodash": "^4.17.4", + "output-file-sync": "^1.1.2", + "path-is-absolute": "^1.0.1", + "slash": "^1.0.0", + "source-map": "^0.5.6", + "v8flags": "^2.1.1" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + }, + "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 + } + } + }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "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" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-add-module-exports": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz", + "integrity": "sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg==", + "dev": true + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "regenerator-runtime": "^0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + }, + "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 + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + } + } + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "dev": true + }, + "basic-auth": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", + "integrity": "sha1-RSIe5Cn37h5QNb4/UVM/HN/SmIQ=" + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "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", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001154", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001154.tgz", + "integrity": "sha512-y9DvdSti8NnYB9Be92ddMZQrcOe04kcQtcxtBx4NkB04+qZ+JUWotnXBJTmxlKudhxNTQ3RRknMwNU2YQl/Org==", + "dev": true + }, + "chai": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", + "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^3.0.1", + "get-func-name": "^2.0.0", + "pathval": "^1.1.0", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "codecov": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.0.tgz", + "integrity": "sha512-7E/S7hmq2CJvCMBMu+aRACO9jxQX1HJug/M3ub8+t84R+5Ai2T5sFMxS3W8P41m2A63+VSAAL4U0aBlqZXkJPw==", + "dev": true, + "requires": { + "argv": "0.0.2", + "ignore-walk": "3.0.3", + "js-yaml": "3.14.0", + "teeny-request": "7.0.1", + "urlgrey": "0.4.4" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.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 + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "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", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "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", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "corser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", + "integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=" + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "deep-eql": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", + "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "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": "1.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz", + "integrity": "sha1-836hXT4T/9m0N9M+GnW1+5eHTLg=", + "dev": true, + "requires": { + "strip-bom": "^2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + } + } + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + } + } + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "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", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecstatic": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.2.tgz", + "integrity": "sha512-fLf9l1hnwrHI2xn9mEDT7KIi22UDqA2jaCwyCbSUJh9a1V+LEUSL/JO/6TIz/QyuBURWUHrFL5Kg2TtO1bkkog==", + "requires": { + "he": "^1.1.1", + "mime": "^1.6.0", + "minimist": "^1.1.0", + "url-join": "^2.0.5" + } + }, + "electron-to-chromium": { + "version": "1.3.585", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.585.tgz", + "integrity": "sha512-xoeqjMQhgHDZM7FiglJAb2aeOxHZWFruUc3MbAGTgE7GB8rr5fTn1Sdh5THGuQtndU3GuXlu91ZKqRivxoCZ/A==", + "dev": true + }, + "elliptic": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", + "dev": true, + "requires": { + "bn.js": "^4.4.0", + "brorand": "^1.0.1", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "errno": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", + "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "dev": true, + "requires": { + "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", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", + "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.9.1", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^4.0.3", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^5.0.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.2.2", + "js-yaml": "^3.13.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "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" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "eslint-config-airbnb-base": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.2.0.tgz", + "integrity": "sha512-1mg/7eoB4AUeB0X1c/ho4vb2gYkNH8Trr/EgCT/aGmKhhG+F6vF5s8+iRBlWAzFIAphxIdp3YfEKgEl0f9Xg+w==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.5", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "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 + }, + "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" + } + }, + "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", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "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 + }, + "espree": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", + "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", + "dev": true, + "requires": { + "acorn": "^6.0.7", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, + "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", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.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 + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "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 + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^2.1.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "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 + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "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" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, + "fileset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/fileset/-/fileset-2.0.3.tgz", + "integrity": "sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA=", + "dev": true, + "requires": { + "glob": "^7.0.3", + "minimatch": "^3.0.3" + } + }, + "fill-range": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", + "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^3.0.0", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "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 + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "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" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "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" + } + }, + "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", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true, + "requires": { + "for-in": "^1.0.1" + } + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "fsu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz", + "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "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 + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", + "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-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true, + "requires": { + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^2.0.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "dev": true, + "requires": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "http-server": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/http-server/-/http-server-0.12.3.tgz", + "integrity": "sha512-be0dKG6pni92bRjq0kvExtj/NrrAd28/8fCXkaI/4piTwQMSDSLMhWyW0NI1V+DBI3aa1HMlQu46/HjVLfmugA==", + "requires": { + "basic-auth": "^1.0.3", + "colors": "^1.4.0", + "corser": "^2.0.1", + "ecstatic": "^3.3.2", + "http-proxy": "^1.18.0", + "minimist": "^1.2.5", + "opener": "^1.5.1", + "portfinder": "^1.0.25", + "secure-compare": "3.0.1", + "union": "~0.5.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "https-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", + "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "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 + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "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" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "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 + }, + "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" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "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": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true + }, + "is-core-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.0.0.tgz", + "integrity": "sha512-jq1AH6C8MuteOoBPwkxHafmByhL9j5q4OaPGdbuD+ZtQJVzH+i6E3BJDQcBA09k57i2Hh2yQbEG8yObZ0jdlWw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true, + "requires": { + "is-primitive": "^2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true, + "optional": true + }, + "is-finite": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", + "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + } + }, + "istanbul": { + "version": "1.1.0-alpha.1", + "resolved": "https://registry.npmjs.org/istanbul/-/istanbul-1.1.0-alpha.1.tgz", + "integrity": "sha1-eBeVZWAYohdMX2DzZ+5dNhy1e3c=", + "dev": true, + "requires": { + "abbrev": "1.0.x", + "async": "1.x", + "istanbul-api": "^1.1.0-alpha", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + } + } + }, + "istanbul-api": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/istanbul-api/-/istanbul-api-1.3.7.tgz", + "integrity": "sha512-4/ApBnMVeEPG3EkSzcw25wDe4N66wxwn+KKn6b47vyek8Xb3NBAcg4xfuQbS7BqcZuTX4wxfD5lVagdggR3gyA==", + "dev": true, + "requires": { + "async": "^2.1.4", + "fileset": "^2.0.2", + "istanbul-lib-coverage": "^1.2.1", + "istanbul-lib-hook": "^1.2.2", + "istanbul-lib-instrument": "^1.10.2", + "istanbul-lib-report": "^1.1.5", + "istanbul-lib-source-maps": "^1.2.6", + "istanbul-reports": "^1.5.1", + "js-yaml": "^3.7.0", + "mkdirp": "^0.5.1", + "once": "^1.4.0" + } + }, + "istanbul-lib-coverage": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", + "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz", + "integrity": "sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw==", + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", + "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.1", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz", + "integrity": "sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz", + "integrity": "sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg==", + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.2.1", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + } + }, + "istanbul-reports": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-1.5.1.tgz", + "integrity": "sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw==", + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "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-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", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "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 + } + } + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "math-random": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", + "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", + "dev": true, + "optional": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "mochawesome": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-3.1.2.tgz", + "integrity": "sha512-w+9QRJNdcOoS4GGj2rJkNl/8KQ34cYyjQfwbFr8tBwjIi2X/jVioAIHUU0gPII5/XpFZd5X24k+IG2DKtdViiQ==", + "dev": true, + "requires": { + "babel-runtime": "^6.20.0", + "chalk": "^2.3.0", + "diff": "^3.4.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.3", + "mochawesome-report-generator": "^3.0.1", + "strip-ansi": "^4.0.0", + "uuid": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "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" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "mochawesome-report-generator": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-3.1.5.tgz", + "integrity": "sha512-/lFmlpY1cPfLXmV/Qb7kprbQS5VYExEaJGRR86rCLYUdLQM5uivIwvulUEt5VV9mbK/GttN2XPb8al7/5VgtOw==", + "dev": true, + "requires": { + "chalk": "^2.3.0", + "dateformat": "^3.0.2", + "fs-extra": "^4.0.2", + "fsu": "^1.0.2", + "lodash.isfunction": "^3.0.8", + "opener": "^1.4.2", + "prop-types": "^15.5.8", + "react": "^16.0.0", + "react-dom": "^16.0.0", + "tcomb": "^3.2.17", + "tcomb-validation": "^3.3.0", + "validator": "^9.1.2", + "yargs": "^10.0.3" + }, + "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" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.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" + } + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "10.1.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.1.2.tgz", + "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" + } + } + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "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 + }, + "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 + } + } + }, + "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", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "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": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nyc": { + "version": "11.7.2", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.7.2.tgz", + "integrity": "sha512-gBt7qwsR1vryYfglVjQRx1D+AtMZW5NbUKxb+lZe8SN8KsheGCPGWEsSC9AGQG+r2+te1+10uPHUCahuqm1nGQ==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "arrify": "^1.0.1", + "caching-transform": "^1.0.0", + "convert-source-map": "^1.5.1", + "debug-log": "^1.0.1", + "default-require-extensions": "^1.0.0", + "find-cache-dir": "^0.1.1", + "find-up": "^2.1.0", + "foreground-child": "^1.5.3", + "glob": "^7.0.6", + "istanbul-lib-coverage": "^1.1.2", + "istanbul-lib-hook": "^1.1.0", + "istanbul-lib-instrument": "^1.10.0", + "istanbul-lib-report": "^1.1.3", + "istanbul-lib-source-maps": "^1.2.3", + "istanbul-reports": "^1.4.0", + "md5-hex": "^1.2.0", + "merge-source-map": "^1.1.0", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.0", + "resolve-from": "^2.0.0", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.1", + "spawn-wrap": "^1.4.2", + "test-exclude": "^4.2.0", + "yargs": "11.1.0", + "yargs-parser": "^8.0.0" + }, + "dependencies": { + "align-text": { + "version": "0.1.4", + "bundled": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "bundled": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "bundled": true, + "dev": true + }, + "append-transform": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "requires": { + "default-require-extensions": "^1.0.0" + } + }, + "archy": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "arr-diff": { + "version": "4.0.0", + "bundled": true, + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "bundled": true, + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "bundled": true, + "dev": true + }, + "arrify": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "async": { + "version": "1.5.2", + "bundled": true + }, + "atob": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "babel-generator": { + "version": "6.26.1", + "bundled": true, + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "bundled": true, + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "bundled": true, + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "base": { + "version": "0.11.2", + "bundled": true, + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "bundled": true, + "dev": true + }, + "cache-base": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "caching-transform": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "md5-hex": "^1.2.0", + "mkdirp": "^0.5.1", + "write-file-atomic": "^1.1.4" + } + }, + "camelcase": { + "version": "1.2.1", + "bundled": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "bundled": true, + "optional": true, + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chalk": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "class-utils": { + "version": "0.3.6", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "cliui": { + "version": "2.1.0", + "bundled": true, + "optional": true, + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "bundled": true, + "optional": true + } + } + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "commondir": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "bundled": true, + "dev": true + }, + "copy-descriptor": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "core-js": { + "version": "2.5.6", + "bundled": true, + "dev": true + }, + "cross-spawn": { + "version": "4.0.2", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "bundled": true + }, + "decode-uri-component": { + "version": "0.2.0", + "bundled": true, + "dev": true + }, + "default-require-extensions": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "strip-bom": "^2.0.0" + } + }, + "define-property": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "dependencies": { + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "detect-indent": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "esutils": { + "version": "2.0.2", + "bundled": true, + "dev": true + }, + "execa": { + "version": "0.7.0", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "bundled": true, + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "fill-range": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "requires": { + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "for-in": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "foreground-child": { + "version": "1.5.6", + "bundled": true, + "dev": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + } + }, + "fragment-cache": { + "version": "0.2.1", + "bundled": true, + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "get-caller-file": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "get-value": { + "version": "2.0.6", + "bundled": true, + "dev": true + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "9.18.0", + "bundled": true, + "dev": true + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "has-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "bundled": true, + "dev": true + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "invariant": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "invert-kv": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-arrayish": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "bundled": true + }, + "is-builtin-module": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "bundled": true, + "dev": true + } + } + }, + "is-extendable": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "is-number": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-odd": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "bundled": true, + "dev": true + } + } + }, + "is-plain-object": { + "version": "2.0.4", + "bundled": true, + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isexe": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "isobject": { + "version": "3.0.1", + "bundled": true, + "dev": true + }, + "istanbul-lib-coverage": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "istanbul-lib-hook": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "append-transform": "^0.4.0" + } + }, + "istanbul-lib-instrument": { + "version": "1.10.1", + "bundled": true, + "dev": true, + "requires": { + "babel-generator": "^6.18.0", + "babel-template": "^6.16.0", + "babel-traverse": "^6.18.0", + "babel-types": "^6.18.0", + "babylon": "^6.18.0", + "istanbul-lib-coverage": "^1.2.0", + "semver": "^5.3.0" + } + }, + "istanbul-lib-report": { + "version": "1.1.3", + "bundled": true, + "dev": true, + "requires": { + "istanbul-lib-coverage": "^1.1.2", + "mkdirp": "^0.5.1", + "path-parse": "^1.0.5", + "supports-color": "^3.1.2" + }, + "dependencies": { + "supports-color": { + "version": "3.2.3", + "bundled": true, + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "1.2.3", + "bundled": true, + "dev": true, + "requires": { + "debug": "^3.1.0", + "istanbul-lib-coverage": "^1.1.2", + "mkdirp": "^0.5.1", + "rimraf": "^2.6.1", + "source-map": "^0.5.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "istanbul-reports": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "handlebars": "^4.0.3" + } + }, + "js-tokens": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "jsesc": { + "version": "1.3.0", + "bundled": true, + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "bundled": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lazy-cache": { + "version": "1.0.4", + "bundled": true, + "optional": true + }, + "lcid": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "bundled": true, + "dev": true + } + } + }, + "longest": { + "version": "1.0.1", + "bundled": true, + "optional": true + }, + "loose-envify": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "js-tokens": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.3", + "bundled": true, + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "map-cache": { + "version": "0.2.2", + "bundled": true, + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5-hex": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "md5-o-matic": "^0.1.1" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "mem": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "merge-source-map": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "bundled": true, + "dev": true + } + } + }, + "micromatch": { + "version": "3.1.10", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "mimic-fn": { + "version": "1.2.0", + "bundled": true, + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mixin-deep": { + "version": "1.3.1", + "bundled": true, + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "nanomatch": { + "version": "1.2.9", + "bundled": true, + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-odd": "^2.0.0", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "normalize-package-data": { + "version": "2.4.0", + "bundled": true, + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "bundled": true, + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "bundled": true, + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-visit": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.6.1", + "bundled": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "p-finally": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "pascalcase": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "path-key": { + "version": "2.0.1", + "bundled": true, + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "bundled": true, + "dev": true + }, + "path-type": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "pify": { + "version": "2.3.0", + "bundled": true, + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "bundled": true, + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "find-up": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "bundled": true, + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "read-pkg": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + } + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "bundled": true, + "dev": true + }, + "regex-not": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "repeat-element": { + "version": "1.1.2", + "bundled": true, + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "bundled": true + }, + "repeating": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "resolve-from": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "bundled": true, + "dev": true + }, + "ret": { + "version": "0.1.15", + "bundled": true, + "dev": true + }, + "right-align": { + "version": "0.1.3", + "bundled": true, + "optional": true, + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-regex": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "set-value": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true + }, + "slide": { + "version": "1.1.6", + "bundled": true, + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "bundled": true + }, + "source-map-resolve": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "atob": "^2.0.0", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "bundled": true, + "dev": true + }, + "spawn-wrap": { + "version": "1.4.2", + "bundled": true, + "dev": true, + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "spdx-correct": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.1.0", + "bundled": true, + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "bundled": true, + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "split-string": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "static-extend": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "bundled": true, + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "string-width": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-eof": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "test-exclude": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "requires": { + "arrify": "^1.0.1", + "micromatch": "^3.1.8", + "object-assign": "^4.1.0", + "read-pkg-up": "^1.0.1", + "require-main-filename": "^1.0.1" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "bundled": true, + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "bundled": true, + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "trim-right": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "bundled": true, + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "yargs": { + "version": "3.10.0", + "bundled": true, + "optional": true, + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "bundled": true, + "optional": true + }, + "union-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "bundled": true, + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unset-value": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "bundled": true, + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "bundled": true, + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "bundled": true, + "dev": true + }, + "use": { + "version": "3.1.0", + "bundled": true, + "dev": true, + "requires": { + "kind-of": "^6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "bundled": true, + "dev": true + } + } + }, + "validate-npm-package-license": { + "version": "3.0.3", + "bundled": true, + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.0", + "bundled": true, + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "bundled": true, + "dev": true + }, + "window-size": { + "version": "0.1.0", + "bundled": true, + "optional": true + }, + "wordwrap": { + "version": "0.0.3", + "bundled": true + }, + "wrap-ansi": { + "version": "2.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "write-file-atomic": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "slide": "^1.1.5" + } + }, + "y18n": { + "version": "3.2.1", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "2.1.2", + "bundled": true, + "dev": true + }, + "yargs": { + "version": "11.1.0", + "bundled": true, + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^9.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "bundled": true, + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + }, + "cliui": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "yargs-parser": { + "version": "9.0.2", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "8.1.0", + "bundled": true, + "dev": true, + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "bundled": true, + "dev": true + } + } + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "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" + } + }, + "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.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true, + "requires": { + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "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", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==" + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.4", + "mkdirp": "^0.5.1", + "object-assign": "^4.1.0" + } + }, + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "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", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true, + "requires": { + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" + } + }, + "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", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true, + "optional": 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 + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "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 + } + } + }, + "pathval": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", + "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "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", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "qs": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "randomatic": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", + "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^4.0.0", + "kind-of": "^6.0.0", + "math-random": "^1.0.1" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true, + "optional": true + }, + "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, + "optional": true + } + } + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "react": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", + "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "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 + } + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "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, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "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, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + } + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true, + "requires": { + "is-equal-shallow": "^0.1.3" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true, + "optional": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" + }, + "resolve": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.18.1.tgz", + "integrity": "sha512-lDfCPaMKfOJXjy0dPayzPdF1phampNWr3qFCjAu+rw/qbQmr5jWH5xN2hwh9QKfw9E5v4hwV7A+jrCmL8yjjqA==", + "dev": true, + "requires": { + "is-core-module": "^2.0.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + } + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "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 + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "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" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "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" + } + }, + "secure-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", + "integrity": "sha1-8aAymzCLIh+uN7mXTz1XjQypmeM=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "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" + } + } + } + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.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" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, + "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", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-events": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", + "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", + "dev": true, + "requires": { + "stubs": "^3.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.2.tgz", + "integrity": "sha512-8oAG/hi14Z4nOVP0z6mdiVZ/wqjDtWSLygMigTzAb+7aPEDTleeFf+WrF+alzecxIRkckkJVn+dTlwzJXORATw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string.prototype.trimstart": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.2.tgz", + "integrity": "sha512-7F6CdBTl5zyu30BJFdzSTlSlLPwODC23Od+iLoVH8X6+3fvDPPuBVVj9iaB1GOsSTSIgVfsfm27R2FGrAPznWg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", + "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "stubs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", + "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "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", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "tcomb": { + "version": "3.2.29", + "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz", + "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==", + "dev": true + }, + "tcomb-validation": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz", + "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==", + "dev": true, + "requires": { + "tcomb": "^3.0.0" + } + }, + "teeny-request": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz", + "integrity": "sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==", + "dev": true, + "requires": { + "http-proxy-agent": "^4.0.0", + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.1", + "stream-events": "^1.0.5", + "uuid": "^8.0.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "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 + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + } + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "ts-node": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.3.tgz", + "integrity": "sha512-2qayBA4vdtVRuDo11DEFSsD/SFsBXQBRZZhbRGSIkmYmVkWjULn/GGMdG10KVqkaGndljfaTD8dKjWgcejO8YA==", + "dev": true, + "requires": { + "arg": "^4.1.0", + "diff": "^3.1.0", + "make-error": "^1.1.1", + "source-map-support": "^0.5.6", + "yn": "^3.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "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": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tslint": { + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.14.0.tgz", + "integrity": "sha512-IUla/ieHVnB8Le7LdQFRGlVJid2T/gaJe5VkjzRVSRR6pA2ODYrnfR1hmxi+5+au9l50jBwpbBL34txgv4NnTQ==", + "dev": true, + "requires": { + "babel-code-frame": "^6.22.0", + "builtin-modules": "^1.1.1", + "chalk": "^2.3.0", + "commander": "^2.12.1", + "diff": "^3.2.0", + "glob": "^7.1.1", + "js-yaml": "^3.7.0", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "resolve": "^1.3.2", + "semver": "^5.3.0", + "tslib": "^1.8.0", + "tsutils": "^2.29.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" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "tsutils": { + "version": "2.29.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", + "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "3.3.3333", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.3333.tgz", + "integrity": "sha512-JjSKsAfuHBE/fB2oZ8NxtRTk5iGcg6hkYXMnZ3Wc+b2RSqejEqTaem11mHASMnFilHrax3sLK0GDzcJrekZYLw==", + "dev": true + }, + "uglify-js": { + "version": "3.11.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.11.4.tgz", + "integrity": "sha512-FyYnoxVL1D6+jDGQpbK5jW6y/2JlVfRfEeQ67BPCUg5wfCjaKOpr2XeceE4QL+MkhxliLtf5EbrMDZgzpt2CNw==", + "dev": true, + "optional": true + }, + "union": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", + "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", + "requires": { + "qs": "^6.4.0" + } + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "optional": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-join": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz", + "integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=" + }, + "urlgrey": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", + "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", + "dev": true + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", + "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "^1.1.1" + } + }, + "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" + } + }, + "validator": { + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==", + "dev": true + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "watchpack": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "optional": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "optional": true + }, + "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, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "optional": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "optional": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "optional": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "optional": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "optional": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "optional": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "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, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true, + "optional": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "optional": true + } + } + }, + "webpack": { + "version": "4.44.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.44.2.tgz", + "integrity": "sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.3.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "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 + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "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" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "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 + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-cli": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.0.tgz", + "integrity": "sha512-t1M7G4z5FhHKJ92WRKwZ1rtvi7rHc0NZoZRbSkol0YKl4HvcC8+DsmGDmK7MmZxHSAetHagiOsjOB6MmzC2TUw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.0", + "findup-sync": "^2.0.0", + "global-modules": "^1.0.0", + "import-local": "^2.0.0", + "interpret": "^1.1.0", + "loader-utils": "^1.1.0", + "supports-color": "^5.5.0", + "v8-compile-cache": "^2.0.2", + "yargs": "^12.0.5" + }, + "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" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "invert-kv": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", + "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "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 + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "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" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.0.tgz", + "integrity": "sha512-upWFJOmDdHN0syLuESuvXDmrRcWd1QafJolHskzaw79uZa7/x53gxQKiR07W59GWY1tFhhU/Th9DrtSfpS782g==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.2", + "yargs-parser": "^20.2.2" + }, + "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 + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cliui": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.3.tgz", + "integrity": "sha512-Gj3QHTkVMPKqwP3f7B4KPkBZRMR9r4rfi5bXFpg1a+Svvj8l7q5CnkBkVQzfxT5DFSsGk2+PascOgL0JYkL2kw==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "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" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.3.tgz", + "integrity": "sha512-emOFRT9WVHw03QSvN5qor9QQT9+sw5vwxfYweivSMHTcAXPefwVae2FjO7JJjj8hCE4CzPOPeFM83VwT29HCww==", + "dev": true + } + } + }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..d0ec6c91 --- /dev/null +++ b/package.json @@ -0,0 +1,86 @@ +{ + "name": "javascript-datastructures-algorithms", + "version": "0.0.1", + "description": "Learning JavaScript Data Structures and Algorithms", + "repository": { + "type": "git", + "url": "git+https://github.com/loiane/javascript-datastructures-algorithms.git" + }, + "keywords": [], + "author": "Loiane Groner", + "license": "MIT", + "bugs": { + "url": "https://github.com/loiane/javascript-datastructures-algorithms/issues" + }, + "homepage": "https://github.com/loiane/javascript-datastructures-algorithms", + "scripts": { + "clean": "rm -rf ./dist ./coverage ./.nyc_output ./coverage.lcov ./mochawesome-report", + "build:js": "babel src/js -d dist/js", + "build:ts": "tsc -p ./ --rootDir ./src/ts", + "build": "npm run build:js && npm run build:ts", + "lint:js": "eslint src/js && eslint test/js", + "lint:ts": "tslint -c tslint.json 'src/ts/**/*.ts' && tslint -c tslint.json 'test/ts/**/*.ts'", + "lint": "npm run lint:js && npm run lint:ts", + "eslintFix": "eslint src/js --fix && eslint test/js --fix", + "test:js": "mocha --compilers js:babel-core/register ./test/js --recursive --reporter mochawesome", + "test:ts": "mocha -r ts-node/register ./test/ts/**/*.spec.ts ./test/ts/**/**/*.spec.ts --recursive", + "test": "npm run test:js && npm run test:ts", + "dev": "npm run clean && npm run lint && npm run webpack && npm run generate-report", + "dev2": "npm run clean && npm run lint && npm run webpack && npm run generate-report2", + "coverage": "npm run generate-report && nyc report --reporter=text-lcov > coverage.lcov && codecov", + "generate-report": "nyc --report-dir coverage npm run test && nyc report --reporter=text", + "generate-report2": "nyc --report-dir coverage npm run test", + "go": "npm run clean && npm run lint && npm run build && npm run test", + "webpack": "webpack --env build", + "serve": "http-server" + }, + "nyc": { + "include": [ + "src/ts/*.ts", + "src/ts/**/*.ts", + "src/js/*.js", + "src/js/**/*.js" + ], + "exclude": [ + "typings" + ], + "extension": [ + ".ts", + ".js" + ], + "reporter": [ + "json", + "html" + ], + "all": true + }, + "devDependencies": { + "@types/chai": "^4.1.2", + "@types/mocha": "^5.0.0", + "babel-cli": "^6.26.0", + "babel-core": "^6.26.3", + "babel-eslint": "^10.0.1", + "babel-loader": "^8.0.5", + "babel-plugin-add-module-exports": "^1.0.0", + "babel-plugin-transform-es2015-modules-umd": "^6.24.1", + "babel-preset-env": "^1.7.0", + "chai": "^4.1.2", + "codecov": "^3.7.1", + "eslint": "^5.15.1", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-plugin-import": "^2.16.0", + "istanbul": "^v1.1.0-alpha.1", + "mocha": "^5.0.4", + "mochawesome": "^3.0.2", + "nyc": "11.7.2", + "ts-node": "8.0.3", + "tslint": "5.14.0", + "typescript": "3.3.3333", + "webpack": "^4.29.6", + "webpack-cli": "3.3.0", + "yargs": "^16.1.0" + }, + "dependencies": { + "http-server": "^0.12.3" + } +} diff --git a/src/js/algorithms/backtracking/rat-in-maze.js b/src/js/algorithms/backtracking/rat-in-maze.js new file mode 100644 index 00000000..ff433130 --- /dev/null +++ b/src/js/algorithms/backtracking/rat-in-maze.js @@ -0,0 +1,41 @@ +function isSafe(maze, x, y) { + const n = maze.length; + if (x >= 0 && y >= 0 && x < n && y < n && maze[x][y] !== 0) { + return true; + } + return false; +} + +function findPath(maze, x, y, solution) { + const n = maze.length; + if (x === n - 1 && y === n - 1) { + solution[x][y] = 1; + return true; + } + if (isSafe(maze, x, y) === true) { + solution[x][y] = 1; + if (findPath(maze, x + 1, y, solution)) { + return true; + } + if (findPath(maze, x, y + 1, solution)) { + return true; + } + solution[x][y] = 0; + return false; + } + return false; +} + +export function ratInAMaze(maze) { + const solution = []; + for (let i = 0; i < maze.length; i++) { + solution[i] = []; + for (let j = 0; j < maze[i].length; j++) { + solution[i][j] = 0; + } + } + if (findPath(maze, 0, 0, solution) === true) { + return solution; + } + return 'NO PATH FOUND'; +} diff --git a/src/js/algorithms/backtracking/sudoku-solver.js b/src/js/algorithms/backtracking/sudoku-solver.js new file mode 100644 index 00000000..6e1a76fc --- /dev/null +++ b/src/js/algorithms/backtracking/sudoku-solver.js @@ -0,0 +1,76 @@ +const UNASSIGNED = 0; + +function usedInRow(matrix, row, num) { + for (let col = 0; col < matrix.length; col++) { + if (matrix[row][col] === num) { + return true; + } + } + return false; +} + +function usedInCol(matrix, col, num) { + for (let row = 0; row < matrix.length; row++) { + if (matrix[row][col] === num) { + return true; + } + } + return false; +} + +function usedInBox(matrix, boxStartRow, boxStartCol, num) { + for (let row = 0; row < 3; row++) { + for (let col = 0; col < 3; col++) { + if (matrix[row + boxStartRow][col + boxStartCol] === num) { + return true; + } + } + } + return false; +} + +function isSafe(matrix, row, col, num) { + return ( + !usedInRow(matrix, row, num) + && !usedInCol(matrix, col, num) + && !usedInBox(matrix, row - (row % 3), col - (col % 3), num) + ); +} +function solveSudoku(matrix) { + let row = 0; + let col = 0; + let checkBlankSpaces = false; + + for (row = 0; row < matrix.length; row++) { + for (col = 0; col < matrix[row].length; col++) { + if (matrix[row][col] === UNASSIGNED) { + checkBlankSpaces = true; + break; + } + } + if (checkBlankSpaces === true) { + break; + } + } + if (checkBlankSpaces === false) { + return true; + } + + for (let num = 1; num <= 9; num++) { + if (isSafe(matrix, row, col, num)) { + matrix[row][col] = num; + if (solveSudoku(matrix)) { + return true; + } + matrix[row][col] = UNASSIGNED; + } + } + return false; +} + +export function sudokuSolver(matrix) { + if (solveSudoku(matrix) === true) { + return matrix; + } + return 'NO SOLUTION EXISTS!'; +} diff --git a/src/js/algorithms/dynamic-programing/knapsack-recursive.js b/src/js/algorithms/dynamic-programing/knapsack-recursive.js new file mode 100644 index 00000000..fbe646e1 --- /dev/null +++ b/src/js/algorithms/dynamic-programing/knapsack-recursive.js @@ -0,0 +1,11 @@ +export function knapSack(capacity, weights, values, n) { + if (n === 0 || capacity === 0) { + return 0; + } + if (weights[n - 1] > capacity) { + return knapSack(capacity, weights, values, n - 1); + } + const a = values[n - 1] + knapSack(capacity - weights[n - 1], weights, values, n - 1); + const b = knapSack(capacity, weights, values, n - 1); + return a > b ? a : b; +} diff --git a/src/js/algorithms/dynamic-programing/knapsack.js b/src/js/algorithms/dynamic-programing/knapsack.js new file mode 100644 index 00000000..9c979360 --- /dev/null +++ b/src/js/algorithms/dynamic-programing/knapsack.js @@ -0,0 +1,41 @@ +function findValues(n, capacity, kS) { + let i = n; + let k = capacity; + // console.log('Items that are part of the solution:'); + while (i > 0 && k > 0) { + if (kS[i][k] !== kS[i - 1][k]) { + // console.log( + // item ' + i + ' can be part of solution w,v: ' + weights[i - 1] + ',' + values[i - 1] + // ); + i--; + k -= kS[i][k]; + } else { + i--; + } + } +} + +export function knapSack(capacity, weights, values, n) { + const kS = []; + for (let i = 0; i <= n; i++) { + kS[i] = []; + } + for (let i = 0; i <= n; i++) { + for (let w = 0; w <= capacity; w++) { + if (i === 0 || w === 0) { + kS[i][w] = 0; + } else if (weights[i - 1] <= w) { + const a = values[i - 1] + kS[i - 1][w - weights[i - 1]]; + const b = kS[i - 1][w]; + kS[i][w] = a > b ? a : b; // max(a,b) + // console.log(a + ' can be part of the solution'); + } else { + kS[i][w] = kS[i - 1][w]; + } + } + // console.log(kS[i].join()); + } + // extra algorithm to find the items that are part of the solution + findValues(n, capacity, kS); + return kS[n][capacity]; +} diff --git a/src/js/algorithms/dynamic-programing/longest-common-subsequence-print.js b/src/js/algorithms/dynamic-programing/longest-common-subsequence-print.js new file mode 100644 index 00000000..e18c6e11 --- /dev/null +++ b/src/js/algorithms/dynamic-programing/longest-common-subsequence-print.js @@ -0,0 +1,51 @@ +function printSolution(solution, wordX, m, n) { + let a = m; + let b = n; + let x = solution[a][b]; + let answer = ''; + while (x !== '0') { + if (solution[a][b] === 'diagonal') { + answer = wordX[a - 1] + answer; + a--; + b--; + } else if (solution[a][b] === 'left') { + b--; + } else if (solution[a][b] === 'top') { + a--; + } + x = solution[a][b]; + } + return answer; +} +export function lcs(wordX, wordY) { + const m = wordX.length; + const n = wordY.length; + const l = []; + const solution = []; + for (let i = 0; i <= m; i++) { + l[i] = []; + solution[i] = []; + for (let j = 0; j <= n; j++) { + l[i][j] = 0; + solution[i][j] = '0'; + } + } + for (let i = 0; i <= m; i++) { + for (let j = 0; j <= n; j++) { + if (i === 0 || j === 0) { + l[i][j] = 0; + } else if (wordX[i - 1] === wordY[j - 1]) { + l[i][j] = l[i - 1][j - 1] + 1; + solution[i][j] = 'diagonal'; + } else { + const a = l[i - 1][j]; + const b = l[i][j - 1]; + l[i][j] = a > b ? a : b; // max(a,b) + solution[i][j] = l[i][j] === l[i - 1][j] ? 'top' : 'left'; + } + } + // console.log(l[i].join()); + // console.log(solution[i].join()); + } + return printSolution(solution, wordX, m, n); +} diff --git a/src/js/algorithms/dynamic-programing/longest-common-subsequence.js b/src/js/algorithms/dynamic-programing/longest-common-subsequence.js new file mode 100644 index 00000000..762c70c6 --- /dev/null +++ b/src/js/algorithms/dynamic-programing/longest-common-subsequence.js @@ -0,0 +1,26 @@ +export function lcs(wordX, wordY) { + const m = wordX.length; + const n = wordY.length; + const l = []; + for (let i = 0; i <= m; i++) { + l[i] = []; + for (let j = 0; j <= n; j++) { + l[i][j] = 0; + } + } + for (let i = 0; i <= m; i++) { + for (let j = 0; j <= n; j++) { + if (i === 0 || j === 0) { + l[i][j] = 0; + } else if (wordX[i - 1] === wordY[j - 1]) { + l[i][j] = l[i - 1][j - 1] + 1; + } else { + const a = l[i - 1][j]; + const b = l[i][j - 1]; + l[i][j] = a > b ? a : b; // max(a,b) + } + } + // console.log(l[i].join()); + } + return l[m][n]; +} diff --git a/src/js/algorithms/dynamic-programing/matrix-chain-multiplication.js b/src/js/algorithms/dynamic-programing/matrix-chain-multiplication.js new file mode 100644 index 00000000..143f5772 --- /dev/null +++ b/src/js/algorithms/dynamic-programing/matrix-chain-multiplication.js @@ -0,0 +1,45 @@ +function printOptimalParenthesis(s, i, j) { + if (i === j) { + // console.log('A[' + i + ']'); + } else { + // console.log('('); + printOptimalParenthesis(s, i, s[i][j]); + printOptimalParenthesis(s, s[i][j] + 1, j); + // console.log(')'); + } +} + +export function matrixChainOrder(p) { + const n = p.length; + const m = []; + const s = []; + for (let i = 1; i <= n; i++) { + m[i] = []; + m[i][i] = 0; + } + for (let i = 0; i <= n; i++) { + // to help printing the optimal solution + s[i] = []; // auxiliary + for (let j = 0; j <= n; j++) { + s[i][j] = 0; + } + } + for (let l = 2; l < n; l++) { + for (let i = 1; i <= (n - l) + 1; i++) { + const j = (i + l) - 1; + m[i][j] = Number.MAX_SAFE_INTEGER; + for (let k = i; k <= j - 1; k++) { + // q = cost/scalar multiplications + const q = m[i][k] + m[k + 1][j] + ((p[i - 1] * p[k]) * p[j]); + if (q < m[i][j]) { + m[i][j] = q; + s[i][j] = k; // s[i,j] = Second auxiliary table that stores k + } + } + } + } + // console.log(m); + // console.log(s); + printOptimalParenthesis(s, 1, n - 1); + return m[1][n - 1]; +} diff --git a/src/js/algorithms/dynamic-programing/min-coin-change.js b/src/js/algorithms/dynamic-programing/min-coin-change.js new file mode 100644 index 00000000..a477c804 --- /dev/null +++ b/src/js/algorithms/dynamic-programing/min-coin-change.js @@ -0,0 +1,32 @@ +export function minCoinChange(coins, amount) { + const cache = []; + + const makeChange = (value) => { + if (!value) { + return []; + } + if (cache[value]) { + return cache[value]; + } + let min = []; + let newMin; + let newAmount; + for (let i = 0; i < coins.length; i++) { + const coin = coins[i]; + newAmount = value - coin; + if (newAmount >= 0) { + newMin = makeChange(newAmount); + } + if ( + newAmount >= 0 + && (newMin.length < min.length - 1 || !min.length) + && (newMin.length || !newAmount) + ) { + min = [coin].concat(newMin); + // console.log('new Min ' + min + ' for ' + amount); + } + } + return (cache[value] = min); + }; + return makeChange(amount); +} diff --git a/src/js/algorithms/graph/breadth-first-search.js b/src/js/algorithms/graph/breadth-first-search.js new file mode 100644 index 00000000..7cf3f395 --- /dev/null +++ b/src/js/algorithms/graph/breadth-first-search.js @@ -0,0 +1,74 @@ +import Queue from '../../data-structures/queue'; + +const Colors = { + WHITE: 0, + GREY: 1, + BLACK: 2 +}; + +const initializeColor = vertices => { + const color = {}; + for (let i = 0; i < vertices.length; i++) { + color[vertices[i]] = Colors.WHITE; + } + return color; +}; + +export const breadthFirstSearch = (graph, startVertex, callback) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + const queue = new Queue(); + + queue.enqueue(startVertex); + + while (!queue.isEmpty()) { + const u = queue.dequeue(); + const neighbors = adjList.get(u); + color[u] = Colors.GREY; + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + color[w] = Colors.GREY; + queue.enqueue(w); + } + } + color[u] = Colors.BLACK; + if (callback) { + callback(u); + } + } +}; + +export const BFS = (graph, startVertex) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + const queue = new Queue(); + const distances = {}; + const predecessors = {}; + queue.enqueue(startVertex); + for (let i = 0; i < vertices.length; i++) { + distances[vertices[i]] = 0; + predecessors[vertices[i]] = null; + } + while (!queue.isEmpty()) { + const u = queue.dequeue(); + const neighbors = adjList.get(u); + color[u] = Colors.GREY; + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + color[w] = Colors.GREY; + distances[w] = distances[u] + 1; + predecessors[w] = u; + queue.enqueue(w); + } + } + color[u] = Colors.BLACK; + } + return { + distances, + predecessors + }; +}; diff --git a/src/js/algorithms/graph/depth-first-search.js b/src/js/algorithms/graph/depth-first-search.js new file mode 100644 index 00000000..8427659f --- /dev/null +++ b/src/js/algorithms/graph/depth-first-search.js @@ -0,0 +1,86 @@ +// import Graph from '../../data-structures/graph'; + +const Colors = { + WHITE: 0, + GREY: 1, + BLACK: 2 +}; + +const initializeColor = vertices => { + const color = {}; + for (let i = 0; i < vertices.length; i++) { + color[vertices[i]] = Colors.WHITE; + } + return color; +}; + +const depthFirstSearchVisit = (u, color, adjList, callback) => { + color[u] = Colors.GREY; + if (callback) { + callback(u); + } + // console.log('Discovered ' + u); + const neighbors = adjList.get(u); + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + depthFirstSearchVisit(w, color, adjList, callback); + } + } + color[u] = Colors.BLACK; + // console.log('explored ' + u); +}; + +export const depthFirstSearch = (graph, callback) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + + for (let i = 0; i < vertices.length; i++) { + if (color[vertices[i]] === Colors.WHITE) { + depthFirstSearchVisit(vertices[i], color, adjList, callback); + } + } +}; + +const DFSVisit = (u, color, d, f, p, time, adjList) => { + // console.log('discovered ' + u); + color[u] = Colors.GREY; + d[u] = ++time.count; + const neighbors = adjList.get(u); + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + p[w] = u; + DFSVisit(w, color, d, f, p, time, adjList); + } + } + color[u] = Colors.BLACK; + f[u] = ++time.count; + // console.log('explored ' + u); +}; + +export const DFS = graph => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + const d = {}; + const f = {}; + const p = {}; + const time = { count: 0 }; + for (let i = 0; i < vertices.length; i++) { + f[vertices[i]] = 0; + d[vertices[i]] = 0; + p[vertices[i]] = null; + } + for (let i = 0; i < vertices.length; i++) { + if (color[vertices[i]] === Colors.WHITE) { + DFSVisit(vertices[i], color, d, f, p, time, adjList); + } + } + return { + discovery: d, + finished: f, + predecessors: p + }; +}; diff --git a/src/js/algorithms/graph/dijkstra.js b/src/js/algorithms/graph/dijkstra.js new file mode 100644 index 00000000..ec223687 --- /dev/null +++ b/src/js/algorithms/graph/dijkstra.js @@ -0,0 +1,32 @@ +const INF = Number.MAX_SAFE_INTEGER; +const minDistance = (dist, visited) => { + let min = INF; + let minIndex = -1; + for (let v = 0; v < dist.length; v++) { + if (visited[v] === false && dist[v] <= min) { + min = dist[v]; + minIndex = v; + } + } + return minIndex; +}; +export const dijkstra = (graph, src) => { + const dist = []; + const visited = []; + const { length } = graph; + for (let i = 0; i < length; i++) { + dist[i] = INF; + visited[i] = false; + } + dist[src] = 0; + for (let i = 0; i < length - 1; i++) { + const u = minDistance(dist, visited); + visited[u] = true; + for (let v = 0; v < length; v++) { + if (!visited[v] && graph[u][v] !== 0 && dist[u] !== INF && dist[u] + graph[u][v] < dist[v]) { + dist[v] = dist[u] + graph[u][v]; + } + } + } + return dist; +}; diff --git a/src/js/algorithms/graph/floyd-warshall.js b/src/js/algorithms/graph/floyd-warshall.js new file mode 100644 index 00000000..d8bb875e --- /dev/null +++ b/src/js/algorithms/graph/floyd-warshall.js @@ -0,0 +1,26 @@ +export const floydWarshall = graph => { + const dist = []; + const { length } = graph; + for (let i = 0; i < length; i++) { + dist[i] = []; + for (let j = 0; j < length; j++) { + if (i === j) { + dist[i][j] = 0; + } else if (!isFinite(graph[i][j])) { + dist[i][j] = Infinity; + } else { + dist[i][j] = graph[i][j]; + } + } + } + for (let k = 0; k < length; k++) { + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + if (dist[i][k] + dist[k][j] < dist[i][j]) { + dist[i][j] = dist[i][k] + dist[k][j]; + } + } + } + } + return dist; +}; diff --git a/src/js/algorithms/graph/kruskal.js b/src/js/algorithms/graph/kruskal.js new file mode 100644 index 00000000..d1435c28 --- /dev/null +++ b/src/js/algorithms/graph/kruskal.js @@ -0,0 +1,57 @@ +const INF = Number.MAX_SAFE_INTEGER; +const find = (i, parent) => { + while (parent[i]) { + i = parent[i]; // eslint-disable-line prefer-destructuring + } + return i; +}; +const union = (i, j, parent) => { + if (i !== j) { + parent[j] = i; + return true; + } + return false; +}; +const initializeCost = graph => { + const cost = []; + const { length } = graph; + for (let i = 0; i < length; i++) { + cost[i] = []; + for (let j = 0; j < length; j++) { + if (graph[i][j] === 0) { + cost[i][j] = INF; + } else { + cost[i][j] = graph[i][j]; + } + } + } + return cost; +}; +export const kruskal = graph => { + const { length } = graph; + const parent = []; + let ne = 0; + let a; + let b; + let u; + let v; + const cost = initializeCost(graph); + while (ne < length - 1) { + for (let i = 0, min = INF; i < length; i++) { + for (let j = 0; j < length; j++) { + if (cost[i][j] < min) { + min = cost[i][j]; + a = u = i; + b = v = j; + } + } + } + u = find(u, parent); + v = find(v, parent); + if (union(u, v, parent)) { + ne++; + } + cost[a][b] = cost[b][a] = INF; + } + return parent; +}; diff --git a/src/js/algorithms/graph/prim.js b/src/js/algorithms/graph/prim.js new file mode 100644 index 00000000..bbb54e95 --- /dev/null +++ b/src/js/algorithms/graph/prim.js @@ -0,0 +1,36 @@ +const INF = Number.MAX_SAFE_INTEGER; +const minKey = (graph, key, visited) => { + // Initialize min value + let min = INF; + let minIndex = 0; + for (let v = 0; v < graph.length; v++) { + if (visited[v] === false && key[v] < min) { + min = key[v]; + minIndex = v; + } + } + return minIndex; +}; +export const prim = graph => { + const parent = []; + const key = []; + const visited = []; + const { length } = graph; + for (let i = 0; i < length; i++) { + key[i] = INF; + visited[i] = false; + } + key[0] = 0; + parent[0] = -1; + for (let i = 0; i < length - 1; i++) { + const u = minKey(graph, key, visited); + visited[u] = true; + for (let v = 0; v < length; v++) { + if (graph[u][v] && !visited[v] && graph[u][v] < key[v]) { + parent[v] = u; + key[v] = graph[u][v]; + } + } + } + return parent; +}; diff --git a/src/js/algorithms/greedy/knapsack.js b/src/js/algorithms/greedy/knapsack.js new file mode 100644 index 00000000..294def52 --- /dev/null +++ b/src/js/algorithms/greedy/knapsack.js @@ -0,0 +1,18 @@ +export function knapSack(capacity, weights, values) { + const n = values.length; + let load = 0; + let val = 0; + for (let i = 0; i < n && load < capacity; i++) { + if (weights[i] <= capacity - load) { + val += values[i]; + load += weights[i]; + // console.log('using item ' + (i + 1) + ' for the solution'); + } else { + const r = (capacity - load) / weights[i]; + val += r * values[i]; + load += weights[i]; + // console.log('using ratio of ' + r + ' for item ' + (i + 1) + ' for the solution'); + } + } + return val; +} diff --git a/src/js/algorithms/greedy/longest-common-subsequence.js b/src/js/algorithms/greedy/longest-common-subsequence.js new file mode 100644 index 00000000..f7ec8272 --- /dev/null +++ b/src/js/algorithms/greedy/longest-common-subsequence.js @@ -0,0 +1,11 @@ +export function lcs(wordX, wordY, m = wordX.length, n = wordY.length) { + if (m === 0 || n === 0) { + return 0; + } + if (wordX[m - 1] === wordY[n - 1]) { + return 1 + lcs(wordX, wordY, m - 1, n - 1); + } + const a = lcs(wordX, wordY, m, n - 1); + const b = lcs(wordX, wordY, m - 1, n); + return a > b ? a : b; +} diff --git a/src/js/algorithms/greedy/matrix-chain-multiplication.js b/src/js/algorithms/greedy/matrix-chain-multiplication.js new file mode 100644 index 00000000..63c5b4ae --- /dev/null +++ b/src/js/algorithms/greedy/matrix-chain-multiplication.js @@ -0,0 +1,14 @@ +export function matrixChainOrder(p, i = 1, j = p.length - 1) { + if (i === j) { + return 0; + } + let min = Number.MAX_SAFE_INTEGER; + for (let k = i; k < j; k++) { + const count = matrixChainOrder(p, i, k) + + matrixChainOrder(p, k + 1, j) + ((p[i - 1] * p[k]) * p[j]); + if (count < min) { + min = count; + } + } + return min; +} diff --git a/src/js/algorithms/greedy/min-coin-change.js b/src/js/algorithms/greedy/min-coin-change.js new file mode 100644 index 00000000..61abfe91 --- /dev/null +++ b/src/js/algorithms/greedy/min-coin-change.js @@ -0,0 +1,12 @@ +export function minCoinChange(coins, amount) { + const change = []; + let total = 0; + for (let i = coins.length; i >= 0; i--) { + const coin = coins[i]; + while (total + coin <= amount) { + change.push(coin); + total += coin; + } + } + return change; +} diff --git a/src/js/algorithms/search/binary-search-recursive.js b/src/js/algorithms/search/binary-search-recursive.js new file mode 100644 index 00000000..d8daa439 --- /dev/null +++ b/src/js/algorithms/search/binary-search-recursive.js @@ -0,0 +1,24 @@ +import { Compare, defaultCompare, DOES_NOT_EXIST } from '../../util'; +import { quickSort } from '../sorting/quicksort'; + +function binarySearchRecursive(array, value, low, high, compareFn = defaultCompare) { + if (low <= high) { + const mid = Math.floor((low + high) / 2); + const element = array[mid]; + if (compareFn(element, value) === Compare.LESS_THAN) { + return binarySearchRecursive(array, value, mid + 1, high, compareFn); + } + if (compareFn(element, value) === Compare.BIGGER_THAN) { + return binarySearchRecursive(array, value, low, mid - 1, compareFn); + } + return mid; + } + return DOES_NOT_EXIST; +} + +export function binarySearch(array, value, compareFn = defaultCompare) { + const sortedArray = quickSort(array); + const low = 0; + const high = sortedArray.length - 1; + return binarySearchRecursive(array, value, low, high, compareFn); +} diff --git a/src/js/algorithms/search/binary-search.js b/src/js/algorithms/search/binary-search.js new file mode 100644 index 00000000..0c2f9fba --- /dev/null +++ b/src/js/algorithms/search/binary-search.js @@ -0,0 +1,24 @@ +import { Compare, defaultCompare, DOES_NOT_EXIST } from '../../util'; +import { quickSort } from '../sorting/quicksort'; + +export function binarySearch(array, value, compareFn = defaultCompare) { + const sortedArray = quickSort(array); + let low = 0; + let high = sortedArray.length - 1; + while (low <= high) { + const mid = Math.floor((low + high) / 2); + const element = sortedArray[mid]; + // console.log('mid element is ' + element); + if (compareFn(element, value) === Compare.LESS_THAN) { + low = mid + 1; + // console.log('low is ' + low); + } else if (compareFn(element, value) === Compare.BIGGER_THAN) { + high = mid - 1; + // console.log('high is ' + high); + } else { + // console.log('found it'); + return mid; + } + } + return DOES_NOT_EXIST; +} diff --git a/src/js/algorithms/search/interpolation-search.js b/src/js/algorithms/search/interpolation-search.js new file mode 100644 index 00000000..2f9f7278 --- /dev/null +++ b/src/js/algorithms/search/interpolation-search.js @@ -0,0 +1,40 @@ +import { + biggerEquals, + Compare, + defaultCompare, + defaultEquals, + defaultDiff, + DOES_NOT_EXIST, + lesserEquals +} from '../../util'; + +export function interpolationSearch( + array, + value, + compareFn = defaultCompare, + equalsFn = defaultEquals, + diffFn = defaultDiff +) { + const { length } = array; + let low = 0; + let high = length - 1; + let position = -1; + let delta = -1; + while ( + low <= high + && biggerEquals(value, array[low], compareFn) + && lesserEquals(value, array[high], compareFn) + ) { + delta = diffFn(value, array[low]) / diffFn(array[high], array[low]); + position = low + Math.floor((high - low) * delta); + if (equalsFn(array[position], value)) { + return position; + } + if (compareFn(array[position], value) === Compare.LESS_THAN) { + low = position + 1; + } else { + high = position - 1; + } + } + return DOES_NOT_EXIST; +} diff --git a/src/js/algorithms/search/min-max-search.js b/src/js/algorithms/search/min-max-search.js new file mode 100644 index 00000000..ddefb113 --- /dev/null +++ b/src/js/algorithms/search/min-max-search.js @@ -0,0 +1,26 @@ +import { defaultCompare, Compare } from '../../util'; + +export function findMaxValue(array, compareFn = defaultCompare) { + if (array && array.length > 0) { + let max = array[0]; + for (let i = 1; i < array.length; i++) { + if (compareFn(max, array[i]) === Compare.LESS_THAN) { + max = array[i]; + } + } + return max; + } + return undefined; +} +export function findMinValue(array, compareFn = defaultCompare) { + if (array && array.length > 0) { + let min = array[0]; + for (let i = 1; i < array.length; i++) { + if (compareFn(min, array[i]) === Compare.BIGGER_THAN) { + min = array[i]; + } + } + return min; + } + return undefined; +} diff --git a/src/js/algorithms/search/sequential-search.js b/src/js/algorithms/search/sequential-search.js new file mode 100644 index 00000000..346c23ac --- /dev/null +++ b/src/js/algorithms/search/sequential-search.js @@ -0,0 +1,10 @@ +import { defaultEquals, DOES_NOT_EXIST } from '../../util'; + +export function sequentialSearch(array, value, equalsFn = defaultEquals) { + for (let i = 0; i < array.length; i++) { + if (equalsFn(value, array[i])) { + return i; + } + } + return DOES_NOT_EXIST; +} diff --git "a/src/js/algorithms/shuffle/fisher\342\200\223yates.js" "b/src/js/algorithms/shuffle/fisher\342\200\223yates.js" new file mode 100644 index 00000000..f951a3ca --- /dev/null +++ "b/src/js/algorithms/shuffle/fisher\342\200\223yates.js" @@ -0,0 +1,11 @@ +import { swap } from '../../util'; + +export function shuffle(array) { + let currentIndex = array.length; + while (currentIndex !== 0) { + const randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + swap(array, currentIndex, randomIndex); + } + return array; +} diff --git a/src/js/algorithms/sorting/bubble-sort-improved.js b/src/js/algorithms/sorting/bubble-sort-improved.js new file mode 100644 index 00000000..a0aba370 --- /dev/null +++ b/src/js/algorithms/sorting/bubble-sort-improved.js @@ -0,0 +1,16 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +export function modifiedBubbleSort(array, compareFn = defaultCompare) { + const { length } = array; + for (let i = 0; i < length; i++) { + // console.log('--- '); + for (let j = 0; j < length - 1 - i; j++) { + // console.log('compare ' + array[j] + ' with ' + array[j + 1]); + if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) { + // console.log('swap ' + array[j] + ' with ' + array[j + 1]); + swap(array, j, j + 1); + } + } + } + return array; +} diff --git a/src/js/algorithms/sorting/bubble-sort.js b/src/js/algorithms/sorting/bubble-sort.js new file mode 100644 index 00000000..7d5b928e --- /dev/null +++ b/src/js/algorithms/sorting/bubble-sort.js @@ -0,0 +1,16 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +export function bubbleSort(array, compareFn = defaultCompare) { + const { length } = array; + for (let i = 0; i < length; i++) { + // console.log('--- '); + for (let j = 0; j < length - 1; j++) { + // console.log('compare ' + array[j] + ' with ' + array[j + 1]); + if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) { + // console.log('swap ' + array[j] + ' with ' + array[j + 1]); + swap(array, j, j + 1); + } + } + } + return array; +} diff --git a/src/js/algorithms/sorting/bucket-sort.js b/src/js/algorithms/sorting/bucket-sort.js new file mode 100644 index 00000000..1a11b699 --- /dev/null +++ b/src/js/algorithms/sorting/bucket-sort.js @@ -0,0 +1,39 @@ +import { insertionSort } from './insertion-sort'; + +function createBuckets(array, bucketSize) { + let minValue = array[0]; + let maxValue = array[0]; + for (let i = 1; i < array.length; i++) { + if (array[i] < minValue) { + minValue = array[i]; + } else if (array[i] > maxValue) { + maxValue = array[i]; + } + } + const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1; + const buckets = []; + for (let i = 0; i < bucketCount; i++) { + buckets[i] = []; + } + for (let i = 0; i < array.length; i++) { + buckets[Math.floor((array[i] - minValue) / bucketSize)].push(array[i]); + } + return buckets; +} +function sortBuckets(buckets) { + const sortedArray = []; + for (let i = 0; i < buckets.length; i++) { + if (buckets[i] != null) { + insertionSort(buckets[i]); + sortedArray.push(...buckets[i]); + } + } + return sortedArray; +} +export function bucketSort(array, bucketSize = 5) { + if (array.length < 2) { + return array; + } + const buckets = createBuckets(array, bucketSize); + return sortBuckets(buckets); +} diff --git a/src/js/algorithms/sorting/counting-sort.js b/src/js/algorithms/sorting/counting-sort.js new file mode 100644 index 00000000..9a19201b --- /dev/null +++ b/src/js/algorithms/sorting/counting-sort.js @@ -0,0 +1,24 @@ +import { findMaxValue } from '../search/min-max-search'; + +export function countingSort(array) { + if (array.length < 2) { + return array; + } + const maxValue = findMaxValue(array); + let sortedIndex = 0; + const counts = new Array(maxValue + 1); + array.forEach(element => { + if (!counts[element]) { + counts[element] = 0; + } + counts[element]++; + }); + // console.log('Frequencies: ' + counts.join()); + counts.forEach((element, i) => { + while (element > 0) { + array[sortedIndex++] = i; + element--; + } + }); + return array; +} diff --git a/src/js/algorithms/sorting/heap-sort.js b/src/js/algorithms/sorting/heap-sort.js new file mode 100644 index 00000000..ff1c10f1 --- /dev/null +++ b/src/js/algorithms/sorting/heap-sort.js @@ -0,0 +1,34 @@ +import { defaultCompare, swap } from '../../util'; + +function heapify(array, index, heapSize, compareFn) { + let largest = index; + const left = (2 * index) + 1; + const right = (2 * index) + 2; + if (left < heapSize && compareFn(array[left], array[index]) > 0) { + largest = left; + } + if (right < heapSize && compareFn(array[right], array[largest]) > 0) { + largest = right; + } + if (largest !== index) { + swap(array, index, largest); + heapify(array, largest, heapSize, compareFn); + } +} + +function buildMaxHeap(array, compareFn) { + for (let i = Math.floor(array.length / 2); i >= 0; i -= 1) { + heapify(array, i, array.length, compareFn); + } + return array; +} + +export default function heapSort(array, compareFn = defaultCompare) { + let heapSize = array.length; + buildMaxHeap(array, compareFn); + while (heapSize > 1) { + swap(array, 0, --heapSize); + heapify(array, 0, heapSize, compareFn); + } + return array; +} diff --git a/src/js/algorithms/sorting/insertion-sort.js b/src/js/algorithms/sorting/insertion-sort.js new file mode 100644 index 00000000..e48689e6 --- /dev/null +++ b/src/js/algorithms/sorting/insertion-sort.js @@ -0,0 +1,19 @@ +import { Compare, defaultCompare } from '../../util'; + +export const insertionSort = (array, compareFn = defaultCompare) => { + const { length } = array; + let temp; + for (let i = 1; i < length; i++) { + let j = i; + temp = array[i]; + // console.log('to be inserted ' + temp); + while (j > 0 && compareFn(array[j - 1], temp) === Compare.BIGGER_THAN) { + // console.log('shift ' + array[j - 1]); + array[j] = array[j - 1]; + j--; + } + // console.log('insert ' + temp); + array[j] = temp; + } + return array; +}; diff --git a/src/js/algorithms/sorting/merge-sort.js b/src/js/algorithms/sorting/merge-sort.js new file mode 100644 index 00000000..5371e714 --- /dev/null +++ b/src/js/algorithms/sorting/merge-sort.js @@ -0,0 +1,21 @@ +import { Compare, defaultCompare } from '../../util'; + +function merge(left, right, compareFn) { + let i = 0; + let j = 0; + const result = []; + while (i < left.length && j < right.length) { + result.push(compareFn(left[i], right[j]) === Compare.LESS_THAN ? left[i++] : right[j++]); + } + return result.concat(i < left.length ? left.slice(i) : right.slice(j)); +} +export function mergeSort(array, compareFn = defaultCompare) { + if (array.length > 1) { + const { length } = array; + const middle = Math.floor(length / 2); + const left = mergeSort(array.slice(0, middle), compareFn); + const right = mergeSort(array.slice(middle, length), compareFn); + array = merge(left, right, compareFn); + } + return array; +} diff --git a/src/js/algorithms/sorting/quicksort.js b/src/js/algorithms/sorting/quicksort.js new file mode 100644 index 00000000..6e27167c --- /dev/null +++ b/src/js/algorithms/sorting/quicksort.js @@ -0,0 +1,38 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +function partition(array, left, right, compareFn) { + const pivot = array[Math.floor((right + left) / 2)]; + let i = left; + let j = right; + + while (i <= j) { + while (compareFn(array[i], pivot) === Compare.LESS_THAN) { + i++; + } + while (compareFn(array[j], pivot) === Compare.BIGGER_THAN) { + j--; + } + if (i <= j) { + swap(array, i, j); + i++; + j--; + } + } + return i; +} +function quick(array, left, right, compareFn) { + let index; + if (array.length > 1) { + index = partition(array, left, right, compareFn); + if (left < index - 1) { + quick(array, left, index - 1, compareFn); + } + if (index < right) { + quick(array, index, right, compareFn); + } + } + return array; +} +export function quickSort(array, compareFn = defaultCompare) { + return quick(array, 0, array.length - 1, compareFn); +} diff --git a/src/js/algorithms/sorting/radix-sort.js b/src/js/algorithms/sorting/radix-sort.js new file mode 100644 index 00000000..db21c37a --- /dev/null +++ b/src/js/algorithms/sorting/radix-sort.js @@ -0,0 +1,44 @@ +import { findMaxValue, findMinValue } from '../search/min-max-search'; + +const getBucketIndex = (value, minValue, significantDigit, radixBase) => + Math.floor(((value - minValue) / significantDigit) % radixBase); + +const countingSortForRadix = (array, radixBase, significantDigit, minValue) => { + let bucketsIndex; + const buckets = []; + const aux = []; + for (let i = 0; i < radixBase; i++) { + buckets[i] = 0; + } + for (let i = 0; i < array.length; i++) { + bucketsIndex = getBucketIndex(array[i], minValue, significantDigit, radixBase); + buckets[bucketsIndex]++; + } + for (let i = 1; i < radixBase; i++) { + buckets[i] += buckets[i - 1]; + } + for (let i = array.length - 1; i >= 0; i--) { + bucketsIndex = getBucketIndex(array[i], minValue, significantDigit, radixBase); + aux[--buckets[bucketsIndex]] = array[i]; + } + for (let i = 0; i < array.length; i++) { + array[i] = aux[i]; + } + return array; +}; +export function radixSort(array, radixBase = 10) { + if (array.length < 2) { + return array; + } + const minValue = findMinValue(array); + const maxValue = findMaxValue(array); + // Perform counting sort for each significant digit, starting at 1 + let significantDigit = 1; + while ((maxValue - minValue) / significantDigit >= 1) { + // console.log('radix sort for digit ' + significantDigit); + array = countingSortForRadix(array, radixBase, significantDigit, minValue); + // console.log(array.join()); + significantDigit *= radixBase; + } + return array; +} diff --git a/src/js/algorithms/sorting/selection-sort.js b/src/js/algorithms/sorting/selection-sort.js new file mode 100644 index 00000000..55a9c2c0 --- /dev/null +++ b/src/js/algorithms/sorting/selection-sort.js @@ -0,0 +1,21 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +export const selectionSort = (array, compareFn = defaultCompare) => { + const { length } = array; + let indexMin; + for (let i = 0; i < length - 1; i++) { + indexMin = i; + // console.log('index ' + array[i]); + for (let j = i; j < length; j++) { + if (compareFn(array[indexMin], array[j]) === Compare.BIGGER_THAN) { + // console.log('new index min ' + array[j]); + indexMin = j; + } + } + if (i !== indexMin) { + // console.log('swap ' + array[i] + ' with ' + array[indexMin]); + swap(array, i, indexMin); + } + } + return array; +}; diff --git a/src/js/algorithms/sorting/shell-sort.js b/src/js/algorithms/sorting/shell-sort.js new file mode 100644 index 00000000..e13127f1 --- /dev/null +++ b/src/js/algorithms/sorting/shell-sort.js @@ -0,0 +1,22 @@ +import { Compare, defaultCompare } from '../../util'; + +export function shellSort(array, compareFn = defaultCompare) { + let increment = array.length / 2; + while (increment > 0) { + for (let i = increment; i < array.length; i++) { + let j = i; + const temp = array[i]; + while (j >= increment && compareFn(array[j - increment], temp) === Compare.BIGGER_THAN) { + array[j] = array[j - increment]; + j -= increment; + } + array[j] = temp; + } + if (increment === 2) { + increment = 1; + } else { + increment = Math.floor((increment * 5) / 11); + } + } + return array; +} diff --git a/src/js/data-structures/avl-tree.js b/src/js/data-structures/avl-tree.js new file mode 100644 index 00000000..8ea3cfb9 --- /dev/null +++ b/src/js/data-structures/avl-tree.js @@ -0,0 +1,169 @@ +import { Compare, defaultCompare } from '../util'; +import BinarySearchTree from './binary-search-tree'; +import { Node } from './models/node'; + +const BalanceFactor = { + UNBALANCED_RIGHT: 1, + SLIGHTLY_UNBALANCED_RIGHT: 2, + BALANCED: 3, + SLIGHTLY_UNBALANCED_LEFT: 4, + UNBALANCED_LEFT: 5 +}; + +export default class AVLTree extends BinarySearchTree { + constructor(compareFn = defaultCompare) { + super(compareFn); + this.compareFn = compareFn; + this.root = null; + } + + getNodeHeight(node) { + if (node == null) { + return -1; + } + return Math.max(this.getNodeHeight(node.left), this.getNodeHeight(node.right)) + 1; + } + + /** + * Left left case: rotate right + * + * b a + * / \ / \ + * a e -> rotationLL(b) -> c b + * / \ / \ + * c d d e + * + * @param node Node + */ + rotationLL(node) { + const tmp = node.left; + node.left = tmp.right; + tmp.right = node; + return tmp; + } + + /** + * Right right case: rotate left + * + * a b + * / \ / \ + * c b -> rotationRR(a) -> a e + * / \ / \ + * d e c d + * + * @param node Node + */ + rotationRR(node) { + const tmp = node.right; + node.right = tmp.left; + tmp.left = node; + return tmp; + } + + /** + * Left right case: rotate left then right + * @param node Node + */ + rotationLR(node) { + node.left = this.rotationRR(node.left); + return this.rotationLL(node); + } + + /** + * Right left case: rotate right then left + * @param node Node + */ + rotationRL(node) { + node.right = this.rotationLL(node.right); + return this.rotationRR(node); + } + + getBalanceFactor(node) { + const heightDifference = this.getNodeHeight(node.left) - this.getNodeHeight(node.right); + switch (heightDifference) { + case -2: + return BalanceFactor.UNBALANCED_RIGHT; + case -1: + return BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT; + case 1: + return BalanceFactor.SLIGHTLY_UNBALANCED_LEFT; + case 2: + return BalanceFactor.UNBALANCED_LEFT; + default: + return BalanceFactor.BALANCED; + } + } + + insert(key) { + this.root = this.insertNode(this.root, key); + } + + insertNode(node, key) { + if (node == null) { + return new Node(key); + } if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + node.left = this.insertNode(node.left, key); + } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + node.right = this.insertNode(node.right, key); + } else { + return node; // duplicated key + } + // verify if tree is balanced + const balanceFactor = this.getBalanceFactor(node); + if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) { + if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) { + // Left left case + node = this.rotationLL(node); + } else { + // Left right case + return this.rotationLR(node); + } + } + if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) { + if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) { + // Right right case + node = this.rotationRR(node); + } else { + // Right left case + return this.rotationRL(node); + } + } + return node; + } + + removeNode(node, key) { + node = super.removeNode(node, key); // {1} + if (node == null) { + return node; + } + // verify if tree is balanced + const balanceFactor = this.getBalanceFactor(node); + if (balanceFactor === BalanceFactor.UNBALANCED_LEFT) { + // Left left case + if ( + this.getBalanceFactor(node.left) === BalanceFactor.BALANCED + || this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT + ) { + return this.rotationLL(node); + } + // Left right case + if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) { + return this.rotationLR(node.left); + } + } + if (balanceFactor === BalanceFactor.UNBALANCED_RIGHT) { + // Right right case + if ( + this.getBalanceFactor(node.right) === BalanceFactor.BALANCED + || this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT + ) { + return this.rotationRR(node); + } + // Right left case + if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) { + return this.rotationRL(node.right); + } + } + return node; + } +} diff --git a/src/js/data-structures/binary-search-tree.js b/src/js/data-structures/binary-search-tree.js new file mode 100644 index 00000000..98795a16 --- /dev/null +++ b/src/js/data-structures/binary-search-tree.js @@ -0,0 +1,152 @@ +import { Compare, defaultCompare } from '../util'; +import { Node } from './models/node'; + +export default class BinarySearchTree { + constructor(compareFn = defaultCompare) { + this.compareFn = compareFn; + this.root = undefined; + } + + insert(key) { + // special case: first key + if (this.root == null) { + this.root = new Node(key); + } else { + this.insertNode(this.root, key); + } + } + + insertNode(node, key) { + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + if (node.left == null) { + node.left = new Node(key); + } else { + this.insertNode(node.left, key); + } + } else if (node.right == null) { + node.right = new Node(key); + } else { + this.insertNode(node.right, key); + } + } + + getRoot() { + return this.root; + } + + search(key) { + return this.searchNode(this.root, key); + } + + searchNode(node, key) { + if (node == null) { + return false; + } + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + return this.searchNode(node.left, key); + } if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + return this.searchNode(node.right, key); + } + return true; + } + + inOrderTraverse(callback) { + this.inOrderTraverseNode(this.root, callback); + } + + inOrderTraverseNode(node, callback) { + if (node != null) { + this.inOrderTraverseNode(node.left, callback); + callback(node.key); + this.inOrderTraverseNode(node.right, callback); + } + } + + preOrderTraverse(callback) { + this.preOrderTraverseNode(this.root, callback); + } + + preOrderTraverseNode(node, callback) { + if (node != null) { + callback(node.key); + this.preOrderTraverseNode(node.left, callback); + this.preOrderTraverseNode(node.right, callback); + } + } + + postOrderTraverse(callback) { + this.postOrderTraverseNode(this.root, callback); + } + + postOrderTraverseNode(node, callback) { + if (node != null) { + this.postOrderTraverseNode(node.left, callback); + this.postOrderTraverseNode(node.right, callback); + callback(node.key); + } + } + + min() { + return this.minNode(this.root); + } + + minNode(node) { + let current = node; + while (current != null && current.left != null) { + current = current.left; + } + return current; + } + + max() { + return this.maxNode(this.root); + } + + maxNode(node) { + let current = node; + while (current != null && current.right != null) { + current = current.right; + } + return current; + } + + remove(key) { + this.root = this.removeNode(this.root, key); + } + + removeNode(node, key) { + if (node == null) { + return undefined; + } + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + node.left = this.removeNode(node.left, key); + return node; + } if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + node.right = this.removeNode(node.right, key); + return node; + } + // key is equal to node.item + // handle 3 special conditions + // 1 - a leaf node + // 2 - a node with only 1 child + // 3 - a node with 2 children + // case 1 + if (node.left == null && node.right == null) { + node = undefined; + return node; + } + // case 2 + if (node.left == null) { + node = node.right; + return node; + } if (node.right == null) { + node = node.left; + return node; + } + // case 3 + const aux = this.minNode(node.right); + node.key = aux.key; + node.right = this.removeNode(node.right, aux.key); + return node; + } +} diff --git a/src/js/data-structures/circular-linked-list.js b/src/js/data-structures/circular-linked-list.js new file mode 100644 index 00000000..4209087a --- /dev/null +++ b/src/js/data-structures/circular-linked-list.js @@ -0,0 +1,75 @@ +import { defaultEquals } from '../util'; +import LinkedList from './linked-list'; +import { Node } from './models/linked-list-models'; + +export default class CircularLinkedList extends LinkedList { + constructor(equalsFn = defaultEquals) { + super(equalsFn); + } + + push(element) { + const node = new Node(element); + let current; + if (this.head == null) { + this.head = node; + } else { + current = this.getElementAt(this.size() - 1); + current.next = node; + } + // set node.next to head - to have circular list + node.next = this.head; + this.count++; + } + + insert(element, index) { + if (index >= 0 && index <= this.count) { + const node = new Node(element); + let current = this.head; + if (index === 0) { + if (this.head == null) { + // if no node in list + this.head = node; + node.next = this.head; + } else { + node.next = current; + current = this.getElementAt(this.size()); + // update last element + this.head = node; + current.next = this.head; + } + } else { + const previous = this.getElementAt(index - 1); + node.next = previous.next; + previous.next = node; + } + this.count++; + return true; + } + return false; + } + + removeAt(index) { + if (index >= 0 && index < this.count) { + let current = this.head; + if (index === 0) { + if (this.size() === 1) { + this.head = undefined; + } else { + const removed = this.head; + current = this.getElementAt(this.size() - 1); + this.head = this.head.next; + current.next = this.head; + current = removed; + } + } else { + // no need to update last element for circular list + const previous = this.getElementAt(index - 1); + current = previous.next; + previous.next = current.next; + } + this.count--; + return current.element; + } + return undefined; + } +} diff --git a/src/js/data-structures/deque.js b/src/js/data-structures/deque.js new file mode 100644 index 00000000..82b50617 --- /dev/null +++ b/src/js/data-structures/deque.js @@ -0,0 +1,88 @@ +// @ts-check + +export default class Deque { + constructor() { + this.count = 0; + this.lowestCount = 0; + this.items = {}; + } + + addFront(element) { + if (this.isEmpty()) { + this.addBack(element); + } else if (this.lowestCount > 0) { + this.lowestCount--; + this.items[this.lowestCount] = element; + } else { + for (let i = this.count; i > 0; i--) { + this.items[i] = this.items[i - 1]; + } + this.count++; + this.items[0] = element; + } + } + + addBack(element) { + this.items[this.count] = element; + this.count++; + } + + removeFront() { + if (this.isEmpty()) { + return undefined; + } + const result = this.items[this.lowestCount]; + delete this.items[this.lowestCount]; + this.lowestCount++; + return result; + } + + removeBack() { + if (this.isEmpty()) { + return undefined; + } + this.count--; + const result = this.items[this.count]; + delete this.items[this.count]; + return result; + } + + peekFront() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.lowestCount]; + } + + peekBack() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.count - 1]; + } + + isEmpty() { + return this.size() === 0; + } + + clear() { + this.items = {}; + this.count = 0; + this.lowestCount = 0; + } + + size() { + return this.count - this.lowestCount; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + let objString = `${this.items[this.lowestCount]}`; + for (let i = this.lowestCount + 1; i < this.count; i++) { + objString = `${objString},${this.items[i]}`; + } + return objString; + } +} diff --git a/src/js/data-structures/dictionary.js b/src/js/data-structures/dictionary.js new file mode 100644 index 00000000..2b0568bd --- /dev/null +++ b/src/js/data-structures/dictionary.js @@ -0,0 +1,81 @@ +import { defaultToString } from '../util'; +import { ValuePair } from './models/value-pair'; + +export default class Dictionary { + constructor(toStrFn = defaultToString) { + this.toStrFn = toStrFn; + this.table = {}; + } + + set(key, value) { + if (key != null && value != null) { + const tableKey = this.toStrFn(key); + this.table[tableKey] = new ValuePair(key, value); + return true; + } + return false; + } + + get(key) { + const valuePair = this.table[this.toStrFn(key)]; + return valuePair == null ? undefined : valuePair.value; + } + + hasKey(key) { + return this.table[this.toStrFn(key)] != null; + } + + remove(key) { + if (this.hasKey(key)) { + delete this.table[this.toStrFn(key)]; + return true; + } + return false; + } + + values() { + return this.keyValues().map(valuePair => valuePair.value); + } + + keys() { + return this.keyValues().map(valuePair => valuePair.key); + } + + keyValues() { + return Object.values(this.table); + } + + forEach(callbackFn) { + const valuePairs = this.keyValues(); + for (let i = 0; i < valuePairs.length; i++) { + const result = callbackFn(valuePairs[i].key, valuePairs[i].value); + if (result === false) { + break; + } + } + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.table).length; + } + + clear() { + this.table = {}; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const valuePairs = this.keyValues(); + let objString = `${valuePairs[0].toString()}`; + for (let i = 1; i < valuePairs.length; i++) { + objString = `${objString},${valuePairs[i].toString()}`; + } + return objString; + } +} diff --git a/src/js/data-structures/doubly-linked-list.js b/src/js/data-structures/doubly-linked-list.js new file mode 100644 index 00000000..e6547ec4 --- /dev/null +++ b/src/js/data-structures/doubly-linked-list.js @@ -0,0 +1,138 @@ +import { defaultEquals } from '../util'; +import LinkedList from './linked-list'; +import { DoublyNode } from './models/linked-list-models'; + +export default class DoublyLinkedList extends LinkedList { + constructor(equalsFn = defaultEquals) { + super(equalsFn); + this.tail = undefined; + } + + push(element) { + const node = new DoublyNode(element); + if (this.head == null) { + this.head = node; + this.tail = node; // NEW + } else { + // attach to the tail node // NEW + this.tail.next = node; + node.prev = this.tail; + this.tail = node; + } + this.count++; + } + + insert(element, index) { + if (index >= 0 && index <= this.count) { + const node = new DoublyNode(element); + let current = this.head; + if (index === 0) { + if (this.head == null) { // NEW + this.head = node; + this.tail = node; // NEW + } else { + node.next = this.head; + this.head.prev = node; // NEW + this.head = node; + } + } else if (index === this.count) { // last item NEW + current = this.tail; + current.next = node; + node.prev = current; + this.tail = node; + } else { + const previous = this.getElementAt(index - 1); + current = previous.next; + node.next = current; + previous.next = node; + current.prev = node; // NEW + node.prev = previous; // NEW + } + this.count++; + return true; + } + return false; + } + + removeAt(index) { + if (index >= 0 && index < this.count) { + let current = this.head; + if (index === 0) { + this.head = this.head.next; + // if there is only one item, then we update tail as well //NEW + if (this.count === 1) { + // {2} + this.tail = undefined; + } else { + this.head.prev = undefined; + } + } else if (index === this.count - 1) { + // last item //NEW + current = this.tail; + this.tail = current.prev; + this.tail.next = undefined; + } else { + current = this.getElementAt(index); + const previous = current.prev; + // link previous with current's next - skip it to remove + previous.next = current.next; + current.next.prev = previous; // NEW + } + this.count--; + return current.element; + } + return undefined; + } + + indexOf(element) { + let current = this.head; + let index = 0; + while (current != null) { + if (this.equalsFn(element, current.element)) { + return index; + } + index++; + current = current.next; + } + return -1; + } + + getHead() { + return this.head; + } + + getTail() { + return this.tail; + } + + clear() { + super.clear(); + this.tail = undefined; + } + + toString() { + if (this.head == null) { + return ''; + } + let objString = `${this.head.element}`; + let current = this.head.next; + while (current != null) { + objString = `${objString},${current.element}`; + current = current.next; + } + return objString; + } + + inverseToString() { + if (this.tail == null) { + return ''; + } + let objString = `${this.tail.element}`; + let previous = this.tail.prev; + while (previous != null) { + objString = `${objString},${previous.element}`; + previous = previous.prev; + } + return objString; + } +} diff --git a/src/js/data-structures/graph.js b/src/js/data-structures/graph.js new file mode 100644 index 00000000..f9bfbe51 --- /dev/null +++ b/src/js/data-structures/graph.js @@ -0,0 +1,50 @@ +import Dictionary from './dictionary'; + +export default class Graph { + constructor(isDirected = false) { + this.isDirected = isDirected; + this.vertices = []; + this.adjList = new Dictionary(); + } + + addVertex(v) { + if (!this.vertices.includes(v)) { + this.vertices.push(v); + this.adjList.set(v, []); // initialize adjacency list with array as well; + } + } + + addEdge(a, b) { + if (!this.adjList.get(a)) { + this.addVertex(a); + } + if (!this.adjList.get(b)) { + this.addVertex(b); + } + this.adjList.get(a).push(b); + if (this.isDirected !== true) { + this.adjList.get(b).push(a); + } + } + + getVertices() { + return this.vertices; + } + + getAdjList() { + return this.adjList; + } + + toString() { + let s = ''; + for (let i = 0; i < this.vertices.length; i++) { + s += `${this.vertices[i]} -> `; + const neighbors = this.adjList.get(this.vertices[i]); + for (let j = 0; j < neighbors.length; j++) { + s += `${neighbors[j]} `; + } + s += '\n'; + } + return s; + } +} diff --git a/src/js/data-structures/hash-table-linear-probing-lazy.js b/src/js/data-structures/hash-table-linear-probing-lazy.js new file mode 100644 index 00000000..d7314f0e --- /dev/null +++ b/src/js/data-structures/hash-table-linear-probing-lazy.js @@ -0,0 +1,132 @@ +import { defaultToString } from '../util'; +import { ValuePairLazy } from './models/value-pair-lazy'; + +export default class HashTableLinearProbingLazy { + constructor(toStrFn = defaultToString) { + this.toStrFn = toStrFn; + this.table = {}; + } + + loseloseHashCode(key) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + hashCode(key) { + return this.loseloseHashCode(key); + } + + put(key, value) { + if (key != null && value != null) { + const position = this.hashCode(key); + if ( + this.table[position] == null + || (this.table[position] != null && this.table[position].isDeleted) + ) { + this.table[position] = new ValuePairLazy(key, value); + } else { + let index = position + 1; + while (this.table[index] != null && !this.table[position].isDeleted) { + index++; + } + this.table[index] = new ValuePairLazy(key, value); + } + return true; + } + return false; + } + + get(key) { + const position = this.hashCode(key); + if (this.table[position] != null) { + if (this.table[position].key === key && !this.table[position].isDeleted) { + return this.table[position].value; + } + let index = position + 1; + while ( + this.table[index] != null + && (this.table[index].key !== key || this.table[index].isDeleted) + ) { + if (this.table[index].key === key && this.table[index].isDeleted) { + return undefined; + } + index++; + } + if ( + this.table[index] != null + && this.table[index].key === key + && !this.table[index].isDeleted + ) { + return this.table[position].value; + } + } + return undefined; + } + + remove(key) { + const position = this.hashCode(key); + if (this.table[position] != null) { + if (this.table[position].key === key && !this.table[position].isDeleted) { + this.table[position].isDeleted = true; + return true; + } + let index = position + 1; + while ( + this.table[index] != null + && (this.table[index].key !== key || this.table[index].isDeleted) + ) { + index++; + } + if ( + this.table[index] != null + && this.table[index].key === key + && !this.table[index].isDeleted + ) { + this.table[index].isDeleted = true; + return true; + } + } + return false; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + let count = 0; + Object.values(this.table).forEach(valuePair => { + count += valuePair.isDeleted === true ? 0 : 1; + }); + return count; + } + + clear() { + this.table = {}; + } + + getTable() { + return this.table; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[ + keys[i] + ].toString()}}`; + } + return objString; + } +} diff --git a/src/js/data-structures/hash-table-linear-probing.js b/src/js/data-structures/hash-table-linear-probing.js new file mode 100644 index 00000000..2b7af8b2 --- /dev/null +++ b/src/js/data-structures/hash-table-linear-probing.js @@ -0,0 +1,124 @@ +import { defaultToString } from '../util'; +import { ValuePair } from './models/value-pair'; + +export default class HashTableLinearProbing { + constructor(toStrFn = defaultToString) { + this.toStrFn = toStrFn; + this.table = {}; + } + + loseloseHashCode(key) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + hashCode(key) { + return this.loseloseHashCode(key); + } + + put(key, value) { + if (key != null && value != null) { + const position = this.hashCode(key); + if (this.table[position] == null) { + this.table[position] = new ValuePair(key, value); + } else { + let index = position + 1; + while (this.table[index] != null) { + index++; + } + this.table[index] = new ValuePair(key, value); + } + return true; + } + return false; + } + + get(key) { + const position = this.hashCode(key); + if (this.table[position] != null) { + if (this.table[position].key === key) { + return this.table[position].value; + } + let index = position + 1; + while (this.table[index] != null && this.table[index].key !== key) { + index++; + } + if (this.table[index] != null && this.table[index].key === key) { + return this.table[position].value; + } + } + return undefined; + } + + remove(key) { + const position = this.hashCode(key); + if (this.table[position] != null) { + if (this.table[position].key === key) { + delete this.table[position]; + this.verifyRemoveSideEffect(key, position); + return true; + } + let index = position + 1; + while (this.table[index] != null && this.table[index].key !== key) { + index++; + } + if (this.table[index] != null && this.table[index].key === key) { + delete this.table[index]; + this.verifyRemoveSideEffect(key, index); + return true; + } + } + return false; + } + + verifyRemoveSideEffect(key, removedPosition) { + const hash = this.hashCode(key); + let index = removedPosition + 1; + while (this.table[index] != null) { + const posHash = this.hashCode(this.table[index].key); + if (posHash <= hash || posHash <= removedPosition) { + this.table[removedPosition] = this.table[index]; + delete this.table[index]; + removedPosition = index; + } + index++; + } + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.table).length; + } + + clear() { + this.table = {}; + } + + getTable() { + return this.table; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[ + keys[i] + ].toString()}}`; + } + return objString; + } +} diff --git a/src/js/data-structures/hash-table-separate-chaining.js b/src/js/data-structures/hash-table-separate-chaining.js new file mode 100644 index 00000000..c8646ae9 --- /dev/null +++ b/src/js/data-structures/hash-table-separate-chaining.js @@ -0,0 +1,106 @@ +import { defaultToString } from '../util'; +import LinkedList from './linked-list'; +import { ValuePair } from './models/value-pair'; + +export default class HashTableSeparateChaining { + constructor(toStrFn = defaultToString) { + this.toStrFn = toStrFn; + this.table = {}; + } + + loseloseHashCode(key) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + hashCode(key) { + return this.loseloseHashCode(key); + } + + put(key, value) { + if (key != null && value != null) { + const position = this.hashCode(key); + if (this.table[position] == null) { + this.table[position] = new LinkedList(); + } + this.table[position].push(new ValuePair(key, value)); + return true; + } + return false; + } + + get(key) { + const position = this.hashCode(key); + const linkedList = this.table[position]; + if (linkedList != null && !linkedList.isEmpty()) { + let current = linkedList.getHead(); + while (current != null) { + if (current.element.key === key) { + return current.element.value; + } + current = current.next; + } + } + return undefined; + } + + remove(key) { + const position = this.hashCode(key); + const linkedList = this.table[position]; + if (linkedList != null && !linkedList.isEmpty()) { + let current = linkedList.getHead(); + while (current != null) { + if (current.element.key === key) { + linkedList.remove(current.element); + if (linkedList.isEmpty()) { + delete this.table[position]; + } + return true; + } + current = current.next; + } + } + return false; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + let count = 0; + Object.values(this.table).forEach(linkedList => { + count += linkedList.size(); + }); + return count; + } + + clear() { + this.table = {}; + } + + getTable() { + return this.table; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[ + keys[i] + ].toString()}}`; + } + return objString; + } +} diff --git a/src/js/data-structures/hash-table.js b/src/js/data-structures/hash-table.js new file mode 100644 index 00000000..79bc51fd --- /dev/null +++ b/src/js/data-structures/hash-table.js @@ -0,0 +1,85 @@ +import { defaultToString } from '../util'; +import { ValuePair } from './models/value-pair'; + +export default class HashTable { + constructor(toStrFn = defaultToString) { + this.toStrFn = toStrFn; + this.table = {}; + } + + loseloseHashCode(key) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + /* djb2HashCode(key) { + const tableKey = this.toStrFn(key); + let hash = 5381; + for (let i = 0; i < tableKey.length; i++) { + hash = (hash * 33) + tableKey.charCodeAt(i); + } + return hash % 1013; + } */ + hashCode(key) { + return this.loseloseHashCode(key); + } + + put(key, value) { + if (key != null && value != null) { + const position = this.hashCode(key); + this.table[position] = new ValuePair(key, value); + return true; + } + return false; + } + + get(key) { + const valuePair = this.table[this.hashCode(key)]; + return valuePair == null ? undefined : valuePair.value; + } + + remove(key) { + const hash = this.hashCode(key); + const valuePair = this.table[hash]; + if (valuePair != null) { + delete this.table[hash]; + return true; + } + return false; + } + + getTable() { + return this.table; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.table).length; + } + + clear() { + this.table = {}; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[keys[i]].toString()}}`; + } + return objString; + } +} diff --git a/src/js/data-structures/heap.js b/src/js/data-structures/heap.js new file mode 100644 index 00000000..889e5957 --- /dev/null +++ b/src/js/data-structures/heap.js @@ -0,0 +1,121 @@ +import { + Compare, defaultCompare, reverseCompare, swap +} from '../util'; + +export class MinHeap { + constructor(compareFn = defaultCompare) { + this.compareFn = compareFn; + this.heap = []; + } + + getLeftIndex(index) { + return (2 * index) + 1; + } + + getRightIndex(index) { + return (2 * index) + 2; + } + + getParentIndex(index) { + if (index === 0) { + return undefined; + } + return Math.floor((index - 1) / 2); + } + + size() { + return this.heap.length; + } + + isEmpty() { + return this.size() <= 0; + } + + clear() { + this.heap = []; + } + + findMinimum() { + return this.isEmpty() ? undefined : this.heap[0]; + } + + insert(value) { + if (value != null) { + const index = this.heap.length; + this.heap.push(value); + this.siftUp(index); + return true; + } + return false; + } + + siftDown(index) { + let element = index; + const left = this.getLeftIndex(index); + const right = this.getRightIndex(index); + const size = this.size(); + if ( + left < size + && this.compareFn(this.heap[element], this.heap[left]) === Compare.BIGGER_THAN + ) { + element = left; + } + if ( + right < size + && this.compareFn(this.heap[element], this.heap[right]) === Compare.BIGGER_THAN + ) { + element = right; + } + if (index !== element) { + swap(this.heap, index, element); + this.siftDown(element); + } + } + + siftUp(index) { + let parent = this.getParentIndex(index); + while ( + index > 0 + && this.compareFn(this.heap[parent], this.heap[index]) === Compare.BIGGER_THAN + ) { + swap(this.heap, parent, index); + index = parent; + parent = this.getParentIndex(index); + } + } + + extract() { + if (this.isEmpty()) { + return undefined; + } + if (this.size() === 1) { + return this.heap.shift(); + } + const removedValue = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.siftDown(0); + return removedValue; + } + + heapify(array) { + if (array) { + this.heap = array; + } + const maxIndex = Math.floor(this.size() / 2) - 1; + for (let i = 0; i <= maxIndex; i++) { + this.siftDown(i); + } + return this.heap; + } + + getAsArray() { + return this.heap; + } +} +export class MaxHeap extends MinHeap { + constructor(compareFn = defaultCompare) { + super(compareFn); + this.compareFn = compareFn; + this.compareFn = reverseCompare(compareFn); + } +} diff --git a/src/js/data-structures/linked-list.js b/src/js/data-structures/linked-list.js new file mode 100644 index 00000000..fdd32d8b --- /dev/null +++ b/src/js/data-structures/linked-list.js @@ -0,0 +1,117 @@ +import { defaultEquals } from '../util'; +import { Node } from './models/linked-list-models'; + +export default class LinkedList { + constructor(equalsFn = defaultEquals) { + this.equalsFn = equalsFn; + this.count = 0; + this.head = undefined; + } + + push(element) { + const node = new Node(element); + let current; + if (this.head == null) { + // catches null && undefined + this.head = node; + } else { + current = this.head; + while (current.next != null) { + current = current.next; + } + current.next = node; + } + this.count++; + } + + getElementAt(index) { + if (index >= 0 && index <= this.count) { + let node = this.head; + for (let i = 0; i < index && node != null; i++) { + node = node.next; + } + return node; + } + return undefined; + } + + insert(element, index) { + if (index >= 0 && index <= this.count) { + const node = new Node(element); + if (index === 0) { + const current = this.head; + node.next = current; + this.head = node; + } else { + const previous = this.getElementAt(index - 1); + node.next = previous.next; + previous.next = node; + } + this.count++; + return true; + } + return false; + } + + removeAt(index) { + if (index >= 0 && index < this.count) { + let current = this.head; + if (index === 0) { + this.head = current.next; + } else { + const previous = this.getElementAt(index - 1); + current = previous.next; + previous.next = current.next; + } + this.count--; + return current.element; + } + return undefined; + } + + remove(element) { + const index = this.indexOf(element); + return this.removeAt(index); + } + + indexOf(element) { + let current = this.head; + for (let i = 0; i < this.size() && current != null; i++) { + if (this.equalsFn(element, current.element)) { + return i; + } + current = current.next; + } + return -1; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return this.count; + } + + getHead() { + return this.head; + } + + clear() { + this.head = undefined; + this.count = 0; + } + + toString() { + if (this.head == null) { + return ''; + } + let objString = `${this.head.element}`; + let current = this.head.next; + for (let i = 1; i < this.size() && current != null; i++) { + objString = `${objString},${current.element}`; + current = current.next; + } + return objString; + } +} diff --git a/src/js/data-structures/models/linked-list-models.js b/src/js/data-structures/models/linked-list-models.js new file mode 100644 index 00000000..31f5dd95 --- /dev/null +++ b/src/js/data-structures/models/linked-list-models.js @@ -0,0 +1,12 @@ +export class Node { + constructor(element, next) { + this.element = element; + this.next = next; + } +} +export class DoublyNode extends Node { + constructor(element, next, prev) { + super(element, next); + this.prev = prev; + } +} diff --git a/src/js/data-structures/models/node.js b/src/js/data-structures/models/node.js new file mode 100644 index 00000000..33b4f371 --- /dev/null +++ b/src/js/data-structures/models/node.js @@ -0,0 +1,11 @@ +export class Node { + constructor(key) { + this.key = key; + this.left = undefined; + this.right = undefined; + } + + toString() { + return `${this.key}`; + } +} diff --git a/src/js/data-structures/models/value-pair-lazy.js b/src/js/data-structures/models/value-pair-lazy.js new file mode 100644 index 00000000..ff2e4398 --- /dev/null +++ b/src/js/data-structures/models/value-pair-lazy.js @@ -0,0 +1,10 @@ +import { ValuePair } from './value-pair'; + +export class ValuePairLazy extends ValuePair { + constructor(key, value, isDeleted = false) { + super(key, value); + this.key = key; + this.value = value; + this.isDeleted = isDeleted; + } +} diff --git a/src/js/data-structures/models/value-pair.js b/src/js/data-structures/models/value-pair.js new file mode 100644 index 00000000..7aa20025 --- /dev/null +++ b/src/js/data-structures/models/value-pair.js @@ -0,0 +1,10 @@ +export class ValuePair { + constructor(key, value) { + this.key = key; + this.value = value; + } + + toString() { + return `[#${this.key}: ${this.value}]`; + } +} diff --git a/src/js/data-structures/queue.js b/src/js/data-structures/queue.js new file mode 100644 index 00000000..6c879004 --- /dev/null +++ b/src/js/data-structures/queue.js @@ -0,0 +1,56 @@ +// @ts-check + +export default class Queue { + constructor() { + this.count = 0; + this.lowestCount = 0; + this.items = {}; + } + + enqueue(element) { + this.items[this.count] = element; + this.count++; + } + + dequeue() { + if (this.isEmpty()) { + return undefined; + } + const result = this.items[this.lowestCount]; + delete this.items[this.lowestCount]; + this.lowestCount++; + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.lowestCount]; + } + + isEmpty() { + return this.size() === 0; + } + + clear() { + this.items = {}; + this.count = 0; + this.lowestCount = 0; + } + + size() { + return this.count - this.lowestCount; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + let objString = `${this.items[this.lowestCount]}`; + for (let i = this.lowestCount + 1; i < this.count; i++) { + objString = `${objString},${this.items[i]}`; + } + return objString; + } +} diff --git a/src/js/data-structures/set.js b/src/js/data-structures/set.js new file mode 100644 index 00000000..0dc29a0c --- /dev/null +++ b/src/js/data-structures/set.js @@ -0,0 +1,103 @@ +export default class Set { + constructor() { + this.items = {}; + } + + add(element) { + if (!this.has(element)) { + this.items[element] = element; + return true; + } + return false; + } + + delete(element) { + if (this.has(element)) { + delete this.items[element]; + return true; + } + return false; + } + + has(element) { + return Object.prototype.hasOwnProperty.call(this.items, element); + } + + values() { + return Object.values(this.items); + } + + union(otherSet) { + const unionSet = new Set(); + this.values().forEach(value => unionSet.add(value)); + otherSet.values().forEach(value => unionSet.add(value)); + return unionSet; + } + + intersection(otherSet) { + const intersectionSet = new Set(); + const values = this.values(); + const otherValues = otherSet.values(); + let biggerSet = values; + let smallerSet = otherValues; + if (otherValues.length - values.length > 0) { + biggerSet = otherValues; + smallerSet = values; + } + smallerSet.forEach(value => { + if (biggerSet.includes(value)) { + intersectionSet.add(value); + } + }); + return intersectionSet; + } + + difference(otherSet) { + const differenceSet = new Set(); + this.values().forEach(value => { + if (!otherSet.has(value)) { + differenceSet.add(value); + } + }); + return differenceSet; + } + + isSubsetOf(otherSet) { + if (this.size() > otherSet.size()) { + return false; + } + let isSubset = true; + this.values().every(value => { + if (!otherSet.has(value)) { + isSubset = false; + return false; + } + return true; + }); + return isSubset; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.items).length; + } + + clear() { + this.items = {}; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const values = this.values(); + let objString = `${values[0]}`; + for (let i = 1; i < values.length; i++) { + objString = `${objString},${values[i].toString()}`; + } + return objString; + } +} diff --git a/src/js/data-structures/sorted-linked-list.js b/src/js/data-structures/sorted-linked-list.js new file mode 100644 index 00000000..6712f6a8 --- /dev/null +++ b/src/js/data-structures/sorted-linked-list.js @@ -0,0 +1,40 @@ +import { Compare, defaultCompare, defaultEquals } from '../util'; +import LinkedList from './linked-list'; + +export default class SortedLinkedList extends LinkedList { + constructor(equalsFn = defaultEquals, compareFn = defaultCompare) { + super(equalsFn); + this.equalsFn = equalsFn; + this.compareFn = compareFn; + } + + push(element) { + if (this.isEmpty()) { + super.push(element); + } else { + const index = this.getIndexNextSortedElement(element); + super.insert(element, index); + } + } + + insert(element, index = 0) { + if (this.isEmpty()) { + return super.insert(element, index === 0 ? index : 0); + } + const pos = this.getIndexNextSortedElement(element); + return super.insert(element, pos); + } + + getIndexNextSortedElement(element) { + let current = this.head; + let i = 0; + for (; i < this.size() && current; i++) { + const comp = this.compareFn(element, current.element); + if (comp === Compare.LESS_THAN) { + return i; + } + current = current.next; + } + return i; + } +} diff --git a/src/js/data-structures/stack-array.js b/src/js/data-structures/stack-array.js new file mode 100644 index 00000000..1491eb2c --- /dev/null +++ b/src/js/data-structures/stack-array.js @@ -0,0 +1,39 @@ +// @ts-check + +export default class StackArray { + constructor() { + this.items = []; + } + + push(element) { + this.items.push(element); + } + + pop() { + return this.items.pop(); + } + + peek() { + return this.items[this.items.length - 1]; + } + + isEmpty() { + return this.items.length === 0; + } + + size() { + return this.items.length; + } + + clear() { + this.items = []; + } + + toArray() { + return this.items; + } + + toString() { + return this.items.toString(); + } +} diff --git a/src/js/data-structures/stack-linked-list.js b/src/js/data-structures/stack-linked-list.js new file mode 100644 index 00000000..902a5d78 --- /dev/null +++ b/src/js/data-structures/stack-linked-list.js @@ -0,0 +1,42 @@ +import DoublyLinkedList from './doubly-linked-list'; + +export default class StackLinkedList { + constructor() { + this.items = new DoublyLinkedList(); + } + + push(element) { + this.items.push(element); + } + + pop() { + if (this.isEmpty()) { + return undefined; + } + const result = this.items.removeAt(this.size() - 1); + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items.getElementAt(this.size() - 1).element; + } + + isEmpty() { + return this.items.isEmpty(); + } + + size() { + return this.items.size(); + } + + clear() { + this.items.clear(); + } + + toString() { + return this.items.toString(); + } +} diff --git a/src/js/data-structures/stack.js b/src/js/data-structures/stack.js new file mode 100644 index 00000000..af9b297b --- /dev/null +++ b/src/js/data-structures/stack.js @@ -0,0 +1,57 @@ +// @ts-check + +export default class Stack { + constructor() { + this.count = 0; + this.items = {}; + } + + push(element) { + this.items[this.count] = element; + this.count++; + } + + pop() { + if (this.isEmpty()) { + return undefined; + } + this.count--; + const result = this.items[this.count]; + delete this.items[this.count]; + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.count - 1]; + } + + isEmpty() { + return this.count === 0; + } + + size() { + return this.count; + } + + clear() { + /* while (!this.isEmpty()) { + this.pop(); + } */ + this.items = {}; + this.count = 0; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + let objString = `${this.items[0]}`; + for (let i = 1; i < this.count; i++) { + objString = `${objString},${this.items[i]}`; + } + return objString; + } +} diff --git a/src/js/index.js b/src/js/index.js new file mode 100644 index 00000000..fa359f81 --- /dev/null +++ b/src/js/index.js @@ -0,0 +1,98 @@ +import * as _util from './util'; + +// chapters 05 and 07 +export const util = _util; + +// chapter 03 +export { default as StackArray } from './data-structures/stack-array'; +export { default as Stack } from './data-structures/stack'; +export { hanoi } from './others/hanoi'; +export { hanoiStack } from './others/hanoi'; +export { baseConverter } from './others/base-converter'; +export { decimalToBinary } from './others/base-converter'; +export { parenthesesChecker } from './others/balanced-symbols'; + +// chapter 04 +export { default as Queue } from './data-structures/queue'; +export { default as Deque } from './data-structures/deque'; +export { hotPotato } from './others/hot-potato'; +export { palindromeChecker } from './others/palindrome-checker'; + +// chapter 05 +export { default as LinkedList } from './data-structures/linked-list'; +export { default as DoublyLinkedList } from './data-structures/doubly-linked-list'; +export { default as CircularLinkedList } from './data-structures/circular-linked-list'; +export { default as SortedLinkedList } from './data-structures/sorted-linked-list'; +export { default as StackLinkedList } from './data-structures/stack-linked-list'; + +// chapter 06 +export { default as Set } from './data-structures/set'; + +// chapter 07 +export { default as Dictionary } from './data-structures/dictionary'; +export { default as HashTable } from './data-structures/hash-table'; +export { default as HashTableSeparateChaining } from './data-structures/hash-table-separate-chaining'; +export { default as HashTableLinearProbing } from './data-structures/hash-table-linear-probing'; +export { default as HashTableLinearProbingLazy } from './data-structures/hash-table-linear-probing-lazy'; + +// chapter 08 +export { factorialIterative } from './others/factorial'; +export { factorial } from './others/factorial'; +export { fibonacci } from './others/fibonacci'; +export { fibonacciIterative } from './others/fibonacci'; +export { fibonacciMemoization } from './others/fibonacci'; + +// chapter 09 +export { default as BinarySearchTree } from './data-structures/binary-search-tree'; +export { default as AVLTree } from './data-structures/avl-tree'; + +// chapter 10 +export { MinHeap } from './data-structures/heap'; +export { MaxHeap } from './data-structures/heap'; +export { default as heapSort } from './algorithms/sorting/heap-sort'; + +// chapter 11 +export { default as Graph } from './data-structures/graph'; +export { breadthFirstSearch } from './algorithms/graph/breadth-first-search'; +export { BFS } from './algorithms/graph/breadth-first-search'; +export { depthFirstSearch } from './algorithms/graph/depth-first-search'; +export { DFS } from './algorithms/graph/depth-first-search'; +export { dijkstra } from './algorithms/graph/dijkstra'; +export { floydWarshall } from './algorithms/graph/floyd-warshall'; +export { prim } from './algorithms/graph/prim'; +export { kruskal } from './algorithms/graph/kruskal'; + +// chapter 12 +export { shuffle } from './algorithms/shuffle/fisher–yates'; + +export { bubbleSort } from './algorithms/sorting/bubble-sort'; +export { modifiedBubbleSort } from './algorithms/sorting/bubble-sort-improved'; +export { bucketSort } from './algorithms/sorting/bucket-sort'; +export { countingSort } from './algorithms/sorting/counting-sort'; +export { insertionSort } from './algorithms/sorting/insertion-sort'; +export { mergeSort } from './algorithms/sorting/merge-sort'; +export { quickSort } from './algorithms/sorting/quicksort'; +export { radixSort } from './algorithms/sorting/radix-sort'; +export { selectionSort } from './algorithms/sorting/selection-sort'; +export { shellSort } from './algorithms/sorting/shell-sort'; + +export { binarySearch } from './algorithms/search/binary-search'; +export { interpolationSearch } from './algorithms/search/interpolation-search'; +export { sequentialSearch } from './algorithms/search/sequential-search'; +export { findMaxValue } from './algorithms/search/min-max-search'; +export { findMinValue } from './algorithms/search/min-max-search'; + +// chapter 14 +export { binarySearch as binarySearchRecursive } from './algorithms/search/binary-search-recursive'; +export { minCoinChange } from './algorithms/dynamic-programing/min-coin-change'; +export { minCoinChange as minCoinChangeGreedy } from './algorithms/greedy/min-coin-change'; +export { knapSack } from './algorithms/dynamic-programing/knapsack'; +export { knapSack as knapSackRecursive } from './algorithms/dynamic-programing/knapsack-recursive'; +export { knapSack as knapSackGreedy } from './algorithms/greedy/knapsack'; +export { lcs } from './algorithms/dynamic-programing/longest-common-subsequence'; +export { lcs as lcsPrint } from './algorithms/dynamic-programing/longest-common-subsequence-print'; +export { lcs as lcsRecursive } from './algorithms/greedy/longest-common-subsequence'; +export { matrixChainOrder } from './algorithms/dynamic-programing/matrix-chain-multiplication'; +export { matrixChainOrder as matrixChainOrderGreedy } from './algorithms/greedy/matrix-chain-multiplication'; +export { ratInAMaze } from './algorithms/backtracking/rat-in-maze'; +export { sudokuSolver } from './algorithms/backtracking/sudoku-solver'; diff --git a/src/js/others/balanced-symbols.js b/src/js/others/balanced-symbols.js new file mode 100644 index 00000000..70bcd27d --- /dev/null +++ b/src/js/others/balanced-symbols.js @@ -0,0 +1,28 @@ +// @ts-check +import Stack from '../data-structures/stack'; + +export function parenthesesChecker(symbols) { + const stack = new Stack(); + const opens = '([{'; + const closers = ')]}'; + let balanced = true; + let index = 0; + let symbol; + let top; + + while (index < symbols.length && balanced) { + symbol = symbols[index]; + if (opens.indexOf(symbol) >= 0) { + stack.push(symbol); + } else if (stack.isEmpty()) { + balanced = false; + } else { + top = stack.pop(); + if (!(opens.indexOf(top) === closers.indexOf(symbol))) { + balanced = false; + } + } + index++; + } + return balanced && stack.isEmpty(); +} diff --git a/src/js/others/base-converter.js b/src/js/others/base-converter.js new file mode 100644 index 00000000..0213b1d7 --- /dev/null +++ b/src/js/others/base-converter.js @@ -0,0 +1,45 @@ +// @ts-check +import Stack from '../data-structures/stack'; + +export function decimalToBinary(decNumber) { + const remStack = new Stack(); + let number = decNumber; + let rem; + let binaryString = ''; + + while (number > 0) { + rem = Math.floor(number % 2); + remStack.push(rem); + number = Math.floor(number / 2); + } + + while (!remStack.isEmpty()) { + binaryString += remStack.pop().toString(); + } + + return binaryString; +} + +export function baseConverter(decNumber, base) { + const remStack = new Stack(); + const digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + let number = decNumber; + let rem; + let baseString = ''; + + if (!(base >= 2 && base <= 36)) { + return ''; + } + + while (number > 0) { + rem = Math.floor(number % base); + remStack.push(rem); + number = Math.floor(number / base); + } + + while (!remStack.isEmpty()) { + baseString += digits[remStack.pop()]; + } + + return baseString; +} diff --git a/src/js/others/factorial.js b/src/js/others/factorial.js new file mode 100644 index 00000000..8592c36e --- /dev/null +++ b/src/js/others/factorial.js @@ -0,0 +1,20 @@ +export function factorialIterative(number) { + if (number < 0) { + return undefined; + } + let total = 1; + for (let n = number; n > 1; n--) { + total *= n; + } + return total; +} + +export function factorial(n) { + if (n < 0) { + return undefined; + } + if (n === 1 || n === 0) { + return 1; + } + return n * factorial(n - 1); +} diff --git a/src/js/others/fibonacci.js b/src/js/others/fibonacci.js new file mode 100644 index 00000000..e0ded2f9 --- /dev/null +++ b/src/js/others/fibonacci.js @@ -0,0 +1,32 @@ +export function fibonacci(n) { + if (n < 1) { + return 0; + } + if (n <= 2) { + return 1; + } + return fibonacci(n - 1) + fibonacci(n - 2); +} + +export function fibonacciIterative(n) { + if (n < 1) { return 0; } + let fibNMinus2 = 0; + let fibNMinus1 = 1; + let fibN = n; + for (let i = 2; i <= n; i++) { + fibN = fibNMinus1 + fibNMinus2; + fibNMinus2 = fibNMinus1; + fibNMinus1 = fibN; + } + return fibN; +} + +export function fibonacciMemoization(n) { + if (n < 1) { return 0; } + const memo = [0, 1]; + const fibonacciMem = num => { + if (memo[num] != null) { return memo[num]; } + return (memo[num] = fibonacciMem(num - 1) + fibonacciMem(num - 2)); + }; + return fibonacciMem(n); +} diff --git a/src/js/others/hanoi.js b/src/js/others/hanoi.js new file mode 100644 index 00000000..b1ab2d0e --- /dev/null +++ b/src/js/others/hanoi.js @@ -0,0 +1,52 @@ +// @ts-check +import Stack from '../data-structures/stack'; + +function towerOfHanoi(plates, source, helper, dest, sourceName, helperName, destName, moves = []) { + if (plates <= 0) { + return moves; + } + if (plates === 1) { + dest.push(source.pop()); + const move = {}; + move[sourceName] = source.toString(); + move[helperName] = helper.toString(); + move[destName] = dest.toString(); + moves.push(move); + } else { + towerOfHanoi(plates - 1, source, dest, helper, sourceName, destName, helperName, moves); + dest.push(source.pop()); + const move = {}; + move[sourceName] = source.toString(); + move[helperName] = helper.toString(); + move[destName] = dest.toString(); + moves.push(move); + towerOfHanoi(plates - 1, helper, source, dest, helperName, sourceName, destName, moves); + } + return moves; +} + +export function hanoiStack(plates) { + const source = new Stack(); + const dest = new Stack(); + const helper = new Stack(); + + for (let i = plates; i > 0; i--) { + source.push(i); + } + + return towerOfHanoi(plates, source, helper, dest, 'source', 'helper', 'dest'); +} + +export function hanoi(plates, source, helper, dest, moves = []) { + if (plates <= 0) { + return moves; + } + if (plates === 1) { + moves.push([source, dest]); + } else { + hanoi(plates - 1, source, dest, helper, moves); + moves.push([source, dest]); + hanoi(plates - 1, helper, source, dest, moves); + } + return moves; +} diff --git a/src/js/others/hot-potato.js b/src/js/others/hot-potato.js new file mode 100644 index 00000000..b34fcc64 --- /dev/null +++ b/src/js/others/hot-potato.js @@ -0,0 +1,22 @@ +import Queue from '../data-structures/queue'; + +export function hotPotato(elementsList, num) { + const queue = new Queue(); + const elimitatedList = []; + + for (let i = 0; i < elementsList.length; i++) { + queue.enqueue(elementsList[i]); + } + + while (queue.size() > 1) { + for (let i = 0; i < num; i++) { + queue.enqueue(queue.dequeue()); + } + elimitatedList.push(queue.dequeue()); + } + + return { + eliminated: elimitatedList, + winner: queue.dequeue() + }; +} diff --git a/src/js/others/palindrome-checker.js b/src/js/others/palindrome-checker.js new file mode 100644 index 00000000..1551e26a --- /dev/null +++ b/src/js/others/palindrome-checker.js @@ -0,0 +1,29 @@ +import Deque from '../data-structures/deque'; + +export function palindromeChecker(aString) { + if ( + aString === undefined + || aString === null + || (aString !== null && aString.length === 0) + ) { + return false; + } + const deque = new Deque(); + const lowerString = aString.toLocaleLowerCase().split(' ').join(''); + let firstChar; + let lastChar; + + for (let i = 0; i < lowerString.length; i++) { + deque.addBack(lowerString.charAt(i)); + } + + while (deque.size() > 1) { + firstChar = deque.removeFront(); + lastChar = deque.removeBack(); + if (firstChar !== lastChar) { + return false; + } + } + + return true; +} diff --git a/src/js/util.js b/src/js/util.js new file mode 100644 index 00000000..9e780fba --- /dev/null +++ b/src/js/util.js @@ -0,0 +1,53 @@ +export const Compare = { + LESS_THAN: -1, + BIGGER_THAN: 1, + EQUALS: 0 +}; + +export const DOES_NOT_EXIST = -1; + +export function lesserEquals(a, b, compareFn) { + const comp = compareFn(a, b); + return comp === Compare.LESS_THAN || comp === Compare.EQUALS; +} + +export function biggerEquals(a, b, compareFn) { + const comp = compareFn(a, b); + return comp === Compare.BIGGER_THAN || comp === Compare.EQUALS; +} + +export function defaultCompare(a, b) { + if (a === b) { + return Compare.EQUALS; + } + return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN; +} + +export function defaultEquals(a, b) { + return a === b; +} + +export function defaultToString(item) { + if (item === null) { + return 'NULL'; + } if (item === undefined) { + return 'UNDEFINED'; + } if (typeof item === 'string' || item instanceof String) { + return `${item}`; + } + return item.toString(); +} + +export function swap(array, a, b) { + /* const temp = array[a]; + array[a] = array[b]; + array[b] = temp; */ + [array[a], array[b]] = [array[b], array[a]]; +} +export function reverseCompare(compareFn) { + return (a, b) => compareFn(b, a); +} + +export function defaultDiff(a, b) { + return Number(a) - Number(b); +} diff --git a/src/ts/algorithms/backtracking/rat-in-maze.ts b/src/ts/algorithms/backtracking/rat-in-maze.ts new file mode 100644 index 00000000..047d4982 --- /dev/null +++ b/src/ts/algorithms/backtracking/rat-in-maze.ts @@ -0,0 +1,54 @@ +export function ratInAMaze(maze: Array>) { + const solution: Array> = []; + + for (let i = 0; i < maze.length; i++) { + solution[i] = []; + for (let j = 0; j < maze[i].length; j++) { + solution[i][j] = 0; + } + } + + if (findPath(maze, 0, 0, solution) === true) { + return solution; + } else { + return 'NO PATH FOUND'; + } +} + +function findPath( + maze: Array>, + x: number, + y: number, + solution: Array> +) { + const n = maze.length; + if (x === n - 1 && y === n - 1) { + solution[x][y] = 1; + return true; + } + + if (isSafe(maze, x, y) === true) { + solution[x][y] = 1; + + if (findPath(maze, x + 1, y, solution)) { + return true; + } + + if (findPath(maze, x, y + 1, solution)) { + return true; + } + + solution[x][y] = 0; + return false; + } + + return false; +} + +function isSafe(maze: Array>, x: number, y: number) { + const n = maze.length; + if (x >= 0 && y >= 0 && x < n && y < n && maze[x][y] !== 0) { + return true; + } + return false; +} diff --git a/src/ts/algorithms/backtracking/sudoku-solver.ts b/src/ts/algorithms/backtracking/sudoku-solver.ts new file mode 100644 index 00000000..3ada1069 --- /dev/null +++ b/src/ts/algorithms/backtracking/sudoku-solver.ts @@ -0,0 +1,87 @@ +const UNASSIGNED = 0; + +export function sudokuSolver(grid: Array>) { + if (solveSudoku(grid) === true) { + return grid; + } else { + return 'NO SOLUTION EXISTS!'; + } +} + +function solveSudoku(grid: Array>) { + let row = 0; + let col = 0; + let checkBlankSpaces = false; + + for (row = 0; row < grid.length; row++) { + for (col = 0; col < grid[row].length; col++) { + if (grid[row][col] === UNASSIGNED) { + checkBlankSpaces = true; + break; + } + } + if (checkBlankSpaces === true) { + break; + } + } + + if (checkBlankSpaces === false) { + return true; + } + + for (let num = 1; num <= 9; num++) { + if (isSafe(grid, row, col, num)) { + grid[row][col] = num; + + if (solveSudoku(grid)) { + return true; + } + + grid[row][col] = UNASSIGNED; + } + } + + return false; +} + +function usedInRow(grid: Array>, row: number, num: number) { + for (let col = 0; col < grid.length; col++) { + if (grid[row][col] === num) { + return true; + } + } + return false; +} + +function usedInCol(grid: Array>, col: number, num: number) { + for (let row = 0; row < grid.length; row++) { + if (grid[row][col] === num) { + return true; + } + } + return false; +} + +function usedInBox( + grid: Array>, + boxStartRow: number, + boxStartCol: number, + num: number +) { + for (let row = 0; row < 3; row++) { + for (let col = 0; col < 3; col++) { + if (grid[row + boxStartRow][col + boxStartCol] === num) { + return true; + } + } + } + return false; +} + +function isSafe(grid: Array>, row: number, col: number, num: number) { + return ( + !usedInRow(grid, row, num) && + !usedInCol(grid, col, num) && + !usedInBox(grid, row - row % 3, col - col % 3, num) + ); +} diff --git a/src/ts/algorithms/dynamic-programing/knapsack-recursive.ts b/src/ts/algorithms/dynamic-programing/knapsack-recursive.ts new file mode 100644 index 00000000..0fce59a5 --- /dev/null +++ b/src/ts/algorithms/dynamic-programing/knapsack-recursive.ts @@ -0,0 +1,13 @@ +export function knapSack(capacity: number, weights: number[], values: number[], n: number): number { + if (n === 0 || capacity === 0) { + return 0; + } + + if (weights[n - 1] > capacity) { + return knapSack(capacity, weights, values, n - 1); + } else { + const a: number = values[n - 1] + knapSack(capacity - weights[n - 1], weights, values, n - 1); + const b: number = knapSack(capacity, weights, values, n - 1); + return a > b ? a : b; + } +} diff --git a/src/ts/algorithms/dynamic-programing/knapsack.ts b/src/ts/algorithms/dynamic-programing/knapsack.ts new file mode 100644 index 00000000..bfa42398 --- /dev/null +++ b/src/ts/algorithms/dynamic-programing/knapsack.ts @@ -0,0 +1,51 @@ +export function knapSack(capacity: number, weights: number[], values: number[], n: number) { + const kS: Array> = []; + + for (let i = 0; i <= n; i++) { + kS[i] = []; + } + + for (let i = 0; i <= n; i++) { + for (let w = 0; w <= capacity; w++) { + if (i === 0 || w === 0) { + kS[i][w] = 0; + } else if (weights[i - 1] <= w) { + const a = values[i - 1] + kS[i - 1][w - weights[i - 1]]; + const b = kS[i - 1][w]; + kS[i][w] = a > b ? a : b; // max(a,b) + // console.log(a + ' can be part of the solution'); + } else { + kS[i][w] = kS[i - 1][w]; + } + } + // console.log(kS[i].join()); + } + + // extra algorithm to find the items that are part of the solution + findValues(n, capacity, kS); + + return kS[n][capacity]; +} + +function findValues( + n: number, + capacity: number, + kS: Array> +) { + let i = n; + let k = capacity; + + // console.log('Items that are part of the solution:'); + + while (i > 0 && k > 0) { + if (kS[i][k] !== kS[i - 1][k]) { + /* console.log( + 'item ' + i + ' can be part of solution w,v: ' + weights[i - 1] + ',' + values[i - 1] + ); */ + i--; + k = k - kS[i][k]; + } else { + i--; + } + } +} diff --git a/src/ts/algorithms/dynamic-programing/longest-common-subsequence-print.ts b/src/ts/algorithms/dynamic-programing/longest-common-subsequence-print.ts new file mode 100644 index 00000000..7c26b986 --- /dev/null +++ b/src/ts/algorithms/dynamic-programing/longest-common-subsequence-print.ts @@ -0,0 +1,60 @@ +export function lcs(wordX: string, wordY: string) { + const m = wordX.length; + const n = wordY.length; + const l: Array> = []; + const solution: Array> = []; + + for (let i = 0; i <= m; i++) { + l[i] = []; + solution[i] = []; + for (let j = 0; j <= n; j++) { + l[i][j] = 0; + solution[i][j] = '0'; + } + } + + for (let i = 0; i <= m; i++) { + for (let j = 0; j <= n; j++) { + if (i === 0 || j === 0) { + l[i][j] = 0; + } else if (wordX[i - 1] === wordY[j - 1]) { + l[i][j] = l[i - 1][j - 1] + 1; + solution[i][j] = 'diagonal'; + } else { + const a = l[i - 1][j]; + const b = l[i][j - 1]; + l[i][j] = a > b ? a : b; // max(a,b) + solution[i][j] = l[i][j] === l[i - 1][j] ? 'top' : 'left'; + } + } + // console.log(l[i].join()); + // console.log(solution[i].join()); + } + + return printSolution(solution, wordX, m, n); + + // return l[m][n]; +} + +function printSolution(solution: Array>, wordX: string, m: number, n: number) { + let a = m; + let b = n; + let x = solution[a][b]; + let answer = ''; + + while (x !== '0') { + if (solution[a][b] === 'diagonal') { + answer = wordX[a - 1] + answer; + a--; + b--; + } else if (solution[a][b] === 'left') { + b--; + } else if (solution[a][b] === 'top') { + a--; + } + x = solution[a][b]; + } + + return answer; + // console.log('lcs: ' + answer); +} diff --git a/src/ts/algorithms/dynamic-programing/longest-common-subsequence.ts b/src/ts/algorithms/dynamic-programing/longest-common-subsequence.ts new file mode 100644 index 00000000..9aa48054 --- /dev/null +++ b/src/ts/algorithms/dynamic-programing/longest-common-subsequence.ts @@ -0,0 +1,29 @@ +export function lcs(wordX: string, wordY: string) { + const m = wordX.length; + const n = wordY.length; + const l: Array> = []; + + for (let i = 0; i <= m; i++) { + l[i] = []; + for (let j = 0; j <= n; j++) { + l[i][j] = 0; + } + } + + for (let i = 0; i <= m; i++) { + for (let j = 0; j <= n; j++) { + if (i === 0 || j === 0) { + l[i][j] = 0; + } else if (wordX[i - 1] === wordY[j - 1]) { + l[i][j] = l[i - 1][j - 1] + 1; + } else { + const a = l[i - 1][j]; + const b = l[i][j - 1]; + l[i][j] = a > b ? a : b; // max(a,b) + } + } + // console.log(l[i].join()); + } + + return l[m][n]; +} diff --git a/src/ts/algorithms/dynamic-programing/matrix-chain-multiplication.ts b/src/ts/algorithms/dynamic-programing/matrix-chain-multiplication.ts new file mode 100644 index 00000000..c2743ec5 --- /dev/null +++ b/src/ts/algorithms/dynamic-programing/matrix-chain-multiplication.ts @@ -0,0 +1,52 @@ +export function matrixChainOrder(p: number[]): number { + const n = p.length; + + const m: Array> = []; + const s: Array> = []; + + for (let i = 1; i <= n; i++) { + m[i] = []; + m[i][i] = 0; + } + + for (let i = 0; i <= n; i++) { + // to help printing the optimal solution + s[i] = []; // auxiliary + for (let j = 0; j <= n; j++) { + s[i][j] = 0; + } + } + + for (let l = 2; l < n; l++) { + for (let i = 1; i <= n - l + 1; i++) { + const j = i + l - 1; + m[i][j] = Number.MAX_SAFE_INTEGER; + for (let k = i; k <= j - 1; k++) { + // q = cost/scalar multiplications + const q = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j]; + if (q < m[i][j]) { + m[i][j] = q; + s[i][j] = k; // s[i,j] = Second auxiliary table that stores k + } + } + } + } + + // console.log(m); + // console.log(s); + + printOptimalParenthesis(s, 1, n - 1); + + return m[1][n - 1]; +} + +function printOptimalParenthesis(s: Array>, i: number, j: number) { + if (i === j) { + // console.log('A[' + i + ']'); + } else { + // console.log('('); + printOptimalParenthesis(s, i, s[i][j]); + printOptimalParenthesis(s, s[i][j] + 1, j); + // console.log(')'); + } +} diff --git a/src/ts/algorithms/dynamic-programing/min-coin-change.ts b/src/ts/algorithms/dynamic-programing/min-coin-change.ts new file mode 100644 index 00000000..85baeb83 --- /dev/null +++ b/src/ts/algorithms/dynamic-programing/min-coin-change.ts @@ -0,0 +1,34 @@ +export function minCoinChange(coins: number[], amount: number) { + const cache: Array> = []; + + // tslint:disable-next-line:no-shadowed-variable + const makeChange = function(amount: number) { + if (!amount) { + return []; + } + if (cache[amount]) { + return cache[amount]; + } + let min: number[] = [], + newMin, + newAmount; + for (let i = 0; i < coins.length; i++) { + const coin = coins[i]; + newAmount = amount - coin; + if (newAmount >= 0) { + newMin = makeChange(newAmount); + } + if ( + newAmount >= 0 && + (newMin.length < min.length - 1 || !min.length) && + (newMin.length || !newAmount) + ) { + min = [coin].concat(newMin); + // console.log('new Min ' + min + ' for ' + amount); + } + } + return (cache[amount] = min); + }; + + return makeChange(amount); +} diff --git a/src/ts/algorithms/graph/breadth-first-search.ts b/src/ts/algorithms/graph/breadth-first-search.ts new file mode 100644 index 00000000..95438007 --- /dev/null +++ b/src/ts/algorithms/graph/breadth-first-search.ts @@ -0,0 +1,78 @@ +import Graph from '../../data-structures/graph'; +import Queue from '../../data-structures/queue'; + +enum Colors { + WHITE = 0, + GREY = 1, + BLACK = 2 +} + +const initializeColor = (vertices: (string | number)[]) => { + const color: any = {}; + for (let i = 0; i < vertices.length; i++) { + color[vertices[i]] = Colors.WHITE; + } + return color; +}; + +export const breadthFirstSearch = (graph: Graph, startVertex: any, callback: Function) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + const queue = new Queue(); + + queue.enqueue(startVertex); + + while (!queue.isEmpty()) { + const u = queue.dequeue(); + const neighbors = adjList.get(u); + color[u] = Colors.GREY; + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + color[w] = Colors.GREY; + queue.enqueue(w); + } + } + color[u] = Colors.BLACK; + if (callback) { + callback(u); + } + } +}; + +export const bfs = (graph: Graph, startVertex: any) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + const queue = new Queue(); + const distances: any = {}; + const predecessors: any = {}; + queue.enqueue(startVertex); + + for (let i = 0; i < vertices.length; i++) { + distances[vertices[i]] = 0; + predecessors[vertices[i]] = null; + } + + while (!queue.isEmpty()) { + const u = queue.dequeue(), + neighbors = adjList.get(u); + color[u] = Colors.GREY; + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + color[w] = Colors.GREY; + distances[w] = distances[u] + 1; + predecessors[w] = u; + queue.enqueue(w); + } + } + color[u] = Colors.BLACK; + } + + return { + distances: distances, + predecessors: predecessors + }; +}; diff --git a/src/ts/algorithms/graph/depth-first-search.ts b/src/ts/algorithms/graph/depth-first-search.ts new file mode 100644 index 00000000..de47c93f --- /dev/null +++ b/src/ts/algorithms/graph/depth-first-search.ts @@ -0,0 +1,102 @@ +import Graph from '../../data-structures/graph'; + +enum Colors { + WHITE = 0, + GREY = 1, + BLACK = 2 +} + +const initializeColor = (vertices: (string | number)[]) => { + const color: any = {}; + for (let i = 0; i < vertices.length; i++) { + color[vertices[i]] = Colors.WHITE; + } + return color; +}; + +const depthFirstSearchVisit = ( + u: string | number, + color: any, + adjList: any, + callback: Function +) => { + color[u] = 'grey'; + if (callback) { + callback(u); + } + // console.log('Discovered ' + u); + const neighbors = adjList.get(u); + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + depthFirstSearchVisit(w, color, adjList, callback); + } + } + color[u] = Colors.BLACK; + // console.log('explored ' + u); +}; + +export const depthFirstSearch = (graph: Graph, callback: Function) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + + for (let i = 0; i < vertices.length; i++) { + if (color[vertices[i]] === Colors.WHITE) { + depthFirstSearchVisit(vertices[i], color, adjList, callback); + } + } +}; + +const DFSVisit = ( + u: string | number, + color: any, + d: any, + f: any, + p: any, + time: any, + adjList: any +) => { + // console.log('discovered ' + u); + color[u] = Colors.GREY; + d[u] = ++time.count; + const neighbors = adjList.get(u); + for (let i = 0; i < neighbors.length; i++) { + const w = neighbors[i]; + if (color[w] === Colors.WHITE) { + p[w] = u; + DFSVisit(w, color, d, f, p, time, adjList); + } + } + color[u] = Colors.BLACK; + f[u] = ++time.count; + // console.log('explored ' + u); +}; + +export const DFS = (graph: Graph) => { + const vertices = graph.getVertices(); + const adjList = graph.getAdjList(); + const color = initializeColor(vertices); + const d: any = {}; + const f: any = {}; + const p: any = {}; + const time = { count: 0 }; + + for (let i = 0; i < vertices.length; i++) { + f[vertices[i]] = 0; + d[vertices[i]] = 0; + p[vertices[i]] = null; + } + + for (let i = 0; i < vertices.length; i++) { + if (color[vertices[i]] === Colors.WHITE) { + DFSVisit(vertices[i], color, d, f, p, time, adjList); + } + } + + return { + discovery: d, + finished: f, + predecessors: p + }; +}; diff --git a/src/ts/algorithms/graph/dijkstra.ts b/src/ts/algorithms/graph/dijkstra.ts new file mode 100644 index 00000000..a3dd4752 --- /dev/null +++ b/src/ts/algorithms/graph/dijkstra.ts @@ -0,0 +1,42 @@ +const INF = Number.MAX_SAFE_INTEGER; + +const minDistance = (dist: number[], visited: boolean[]) => { + let min = INF; + let minIndex = -1; + + for (let v = 0; v < dist.length; v++) { + if (visited[v] === false && dist[v] <= min) { + min = dist[v]; + minIndex = v; + } + } + + return minIndex; +}; + +export const dijkstra = (graph: number[][], src: number) => { + const dist: number[] = []; + const visited: boolean[] = []; + const length = graph.length; + + for (let i = 0; i < length; i++) { + dist[i] = INF; + visited[i] = false; + } + + dist[src] = 0; + + for (let i = 0; i < length - 1; i++) { + const u = minDistance(dist, visited); + + visited[u] = true; + + for (let v = 0; v < length; v++) { + if (!visited[v] && graph[u][v] !== 0 && dist[u] !== INF && dist[u] + graph[u][v] < dist[v]) { + dist[v] = dist[u] + graph[u][v]; + } + } + } + + return dist; +}; diff --git a/src/ts/algorithms/graph/floyd-warshall.ts b/src/ts/algorithms/graph/floyd-warshall.ts new file mode 100644 index 00000000..7699c6e8 --- /dev/null +++ b/src/ts/algorithms/graph/floyd-warshall.ts @@ -0,0 +1,29 @@ +export const floydWarshall = (graph: number[][]) => { + const dist: number[][] = []; + const length = graph.length; + + for (let i = 0; i < length; i++) { + dist[i] = []; + for (let j = 0; j < length; j++) { + if (i === j) { + dist[i][j] = 0; + } else if (!isFinite(graph[i][j])) { + dist[i][j] = Infinity; + } else { + dist[i][j] = graph[i][j]; + } + } + } + + for (let k = 0; k < length; k++) { + for (let i = 0; i < length; i++) { + for (let j = 0; j < length; j++) { + if (dist[i][k] + dist[k][j] < dist[i][j]) { + dist[i][j] = dist[i][k] + dist[k][j]; + } + } + } + } + + return dist; +}; diff --git a/src/ts/algorithms/graph/kruskal.ts b/src/ts/algorithms/graph/kruskal.ts new file mode 100644 index 00000000..978b1e3b --- /dev/null +++ b/src/ts/algorithms/graph/kruskal.ts @@ -0,0 +1,67 @@ +const INF = Number.MAX_SAFE_INTEGER; + +const find = (i: number, parent: number[]) => { + while (parent[i]) { + i = parent[i]; + } + return i; +}; + +const union = (i: number, j: number, parent: number[]) => { + if (i !== j) { + parent[j] = i; + return true; + } + return false; +}; + +const initializeCost = (graph: number[][]) => { + const cost: number[][] = []; + const length = graph.length; + for (let i = 0; i < length; i++) { + cost[i] = []; + for (let j = 0; j < length; j++) { + if (graph[i][j] === 0) { + cost[i][j] = INF; + } else { + cost[i][j] = graph[i][j]; + } + } + } + return cost; +}; + +export const kruskal = (graph: number[][]) => { + const length = graph.length; + const parent: number[] = []; + let ne = 0; + let a; + let b; + let u; + let v; + + const cost = initializeCost(graph); + + while (ne < length - 1) { + for (let i = 0, min = INF; i < length; i++) { + for (let j = 0; j < length; j++) { + if (cost[i][j] < min) { + min = cost[i][j]; + a = u = i; + b = v = j; + } + } + } + + u = find(u, parent); + v = find(v, parent); + + if (union(u, v, parent)) { + ne++; + } + + cost[a][b] = cost[b][a] = INF; + } + + return parent; +}; diff --git a/src/ts/algorithms/graph/prim.ts b/src/ts/algorithms/graph/prim.ts new file mode 100644 index 00000000..85892d03 --- /dev/null +++ b/src/ts/algorithms/graph/prim.ts @@ -0,0 +1,45 @@ +const INF = Number.MAX_SAFE_INTEGER; + +const minKey = (graph: number[][], key: number[], visited: boolean[]) => { + // Initialize min value + let min = INF; + let minIndex = 0; + + for (let v = 0; v < graph.length; v++) { + if (visited[v] === false && key[v] < min) { + min = key[v]; + minIndex = v; + } + } + + return minIndex; +}; + +export const prim = (graph: number[][]) => { + const parent: number[] = []; + const key: number[] = []; + const visited: boolean[] = []; + const length = graph.length; + + for (let i = 0; i < length; i++) { + key[i] = INF; + visited[i] = false; + } + + key[0] = 0; + parent[0] = -1; + + for (let i = 0; i < length - 1; i++) { + const u = minKey(graph, key, visited); + visited[u] = true; + + for (let v = 0; v < length; v++) { + if (graph[u][v] && visited[v] === false && graph[u][v] < key[v]) { + parent[v] = u; + key[v] = graph[u][v]; + } + } + } + + return parent; +}; diff --git a/src/ts/algorithms/greedy/knapsack.ts b/src/ts/algorithms/greedy/knapsack.ts new file mode 100644 index 00000000..101ebae5 --- /dev/null +++ b/src/ts/algorithms/greedy/knapsack.ts @@ -0,0 +1,19 @@ +export function knapSack(capacity: number, weights: number[], values: number[]) { + const n = values.length; + let load = 0; + let val = 0; + + for (let i = 0; i < n && load < capacity; i++) { + if (weights[i] <= capacity - load) { + val += values[i]; + load += weights[i]; + // console.log('using item ' + (i + 1) + ' for the solution'); + } else { + const r = (capacity - load) / weights[i]; + val += r * values[i]; + load += weights[i]; + // console.log('using ratio of ' + r + ' for item ' + (i + 1) + ' for the solution'); + } + } + return val; +} diff --git a/src/ts/algorithms/greedy/longest-common-subsequence.ts b/src/ts/algorithms/greedy/longest-common-subsequence.ts new file mode 100644 index 00000000..a7239f66 --- /dev/null +++ b/src/ts/algorithms/greedy/longest-common-subsequence.ts @@ -0,0 +1,13 @@ +export function lcs(wordX: string, wordY: string, m = wordX.length, n = wordY.length): number { + if (m === 0 || n === 0) { + return 0; + } + + if (wordX[m - 1] === wordY[n - 1]) { + return 1 + lcs(wordX, wordY, m - 1, n - 1); + } else { + const a = lcs(wordX, wordY, m, n - 1); + const b = lcs(wordX, wordY, m - 1, n); + return a > b ? a : b; + } +} diff --git a/src/ts/algorithms/greedy/matrix-chain-multiplication.ts b/src/ts/algorithms/greedy/matrix-chain-multiplication.ts new file mode 100644 index 00000000..fc23fced --- /dev/null +++ b/src/ts/algorithms/greedy/matrix-chain-multiplication.ts @@ -0,0 +1,18 @@ +export function matrixChainOrder(p: number[], i = 1, j = p.length - 1): number { + if (i === j) { + return 0; + } + + let min = Number.MAX_SAFE_INTEGER; + + for (let k = i; k < j; k++) { + const count = + matrixChainOrder(p, i, k) + matrixChainOrder(p, k + 1, j) + p[i - 1] * p[k] * p[j]; + + if (count < min) { + min = count; + } + } + + return min; +} diff --git a/src/ts/algorithms/greedy/min-coin-change.ts b/src/ts/algorithms/greedy/min-coin-change.ts new file mode 100644 index 00000000..14f3fbf6 --- /dev/null +++ b/src/ts/algorithms/greedy/min-coin-change.ts @@ -0,0 +1,12 @@ +export function minCoinChange(coins: number[], amount: number) { + const change: number[] = []; + let total = 0; + for (let i = coins.length; i >= 0; i--) { + const coin = coins[i]; + while (total + coin <= amount) { + change.push(coin); + total += coin; + } + } + return change; +} diff --git a/src/ts/algorithms/math/find-divisors.ts b/src/ts/algorithms/math/find-divisors.ts new file mode 100644 index 00000000..ea454418 --- /dev/null +++ b/src/ts/algorithms/math/find-divisors.ts @@ -0,0 +1,22 @@ +export const findDivisors = (num: number) => { + const divisors = []; + + const sqrt = Math.floor(Math.sqrt(num)); + + for (let i = 1; i <= sqrt; i++) { + if (num % i === 0) { + divisors.push(i); + if (i !== sqrt) { + divisors.push(Math.floor(num / i)); + } + } + } + + if (num >= 2 && !divisors.includes(num)) { + divisors.push(num); + } + + divisors.sort((a, b) => a - b); + + return divisors; +}; diff --git a/src/ts/algorithms/math/gcd.ts b/src/ts/algorithms/math/gcd.ts new file mode 100644 index 00000000..35818deb --- /dev/null +++ b/src/ts/algorithms/math/gcd.ts @@ -0,0 +1,22 @@ +export const gcd = (num1: number, num2: number): number => { + if (num1 === 0 || num2 === 0) { + return 0; + } + if (num1 === num2) { + return num1; + } + if (num1 > num2) { + return gcd(num1 - num2, num2); + } + return gcd(num1, num2 - num1); +}; + +export const gcdArray = (num: number[]) => { + let result = num[0]; + + for (let i = 1; i < num.length; i++) { + result = gcd(num[i], result); + } + + return result; +}; diff --git a/src/ts/algorithms/math/greatest-difference.ts b/src/ts/algorithms/math/greatest-difference.ts new file mode 100644 index 00000000..a0412445 --- /dev/null +++ b/src/ts/algorithms/math/greatest-difference.ts @@ -0,0 +1,20 @@ +export const greatestDifference = (numbers: number[]) => { + let index = 0; + let largest = numbers[0]; + const length = numbers.length; + let number; + let smallest = numbers[0]; + + for (index; index < length; index++) { + number = numbers[index]; + + if (number > largest) { + largest = number; + } + if (number < smallest) { + smallest = number; + } + } + + return largest - smallest; +}; diff --git a/src/ts/algorithms/math/lcm.ts b/src/ts/algorithms/math/lcm.ts new file mode 100644 index 00000000..a4c4ac37 --- /dev/null +++ b/src/ts/algorithms/math/lcm.ts @@ -0,0 +1,20 @@ +import { gcd } from './gcd'; + +export const lcm = (num1: number, num2: number) => { + if (num1 === 0 || num2 === 0) { + return 0; + } + num1 = Math.abs(num1); + num2 = Math.abs(num2); + return (num1 * num2) / gcd(num1, num2); +}; + +export const lcmArray = (num: number[]) => { + let result = num[0]; + + for (let i = 1; i < num.length; i++) { + result = num[i] * result / gcd(num[i], result); + } + + return result; +}; diff --git a/src/ts/algorithms/math/primality-test.ts b/src/ts/algorithms/math/primality-test.ts new file mode 100644 index 00000000..f04e899d --- /dev/null +++ b/src/ts/algorithms/math/primality-test.ts @@ -0,0 +1,37 @@ +export const isPrime = (n: number) => { + if (n <= 1) { + return false; + } + + const sqrt = Math.floor(Math.sqrt(n)); + for (let i = 2; i <= sqrt; i++) { + if (n % i === 0) { + return false; + } + } + + return true; +}; + +export const testPrime = (n: number) => { + if (n <= 1) { + return false; + } else { + if (n === 2 || n === 3) { + return true; + } else if (n % 2 === 0) { + return false; + } else { + const sqrt = Math.floor(Math.sqrt(n)); + for (let i = 3; i <= sqrt; i += 2) { + if (n % i === 0) { + return false; + } + } + } + } + return true; +}; + +// tslint:disable-next-line:max-line-length +export const isPrime2 = (n: number) => (n >= 2) ? (![...Array(n).keys()].slice(2).map(i => !(n % i)).includes(true) && ![0, 1].includes(n)) : false; diff --git a/src/ts/algorithms/math/sieve-eratosthenes.ts b/src/ts/algorithms/math/sieve-eratosthenes.ts new file mode 100644 index 00000000..353389a1 --- /dev/null +++ b/src/ts/algorithms/math/sieve-eratosthenes.ts @@ -0,0 +1,27 @@ +export const sieveOfEratosthenes = (n: number) => { + + const sieve: boolean[] = []; + const primes: number[] = []; + + sieve[1] = false; + + for (let i = 2; i <= n; i++) { + sieve[i] = true; + } + + for (let p = 2; p * p <= n; p++) { + if (sieve[p]) { + for (let i = p * 2; i <= n; i += p) { + sieve[i] = false; + } + } + } + + sieve.forEach((value, index) => { + if (value) { + primes.push(index); + } + }, primes); + + return primes; +}; diff --git a/src/ts/algorithms/search/binary-search-recursive.ts b/src/ts/algorithms/search/binary-search-recursive.ts new file mode 100644 index 00000000..6d902139 --- /dev/null +++ b/src/ts/algorithms/search/binary-search-recursive.ts @@ -0,0 +1,32 @@ +import { Compare, defaultCompare, DOES_NOT_EXIST } from '../../util'; +import { quickSort } from '../sorting/quicksort'; + +function binarySearchRecursive( + array: T[], + value: T, + low: number, + high: number, + compareFn = defaultCompare +): number { + if (low <= high) { + const mid = Math.floor((low + high) / 2); + const element = array[mid]; + + if (compareFn(element, value) === Compare.LESS_THAN) { + return binarySearchRecursive(array, value, mid + 1, high, compareFn); + } else if (compareFn(element, value) === Compare.BIGGER_THAN) { + return binarySearchRecursive(array, value, low, mid - 1, compareFn); + } else { + return mid; + } + } + return DOES_NOT_EXIST; +} + +export function binarySearch(array: T[], value: T, compareFn = defaultCompare) { + const sortedArray = quickSort(array); + const low = 0; + const high = sortedArray.length - 1; + + return binarySearchRecursive(array, value, low, high, compareFn); +} diff --git a/src/ts/algorithms/search/binary-search.ts b/src/ts/algorithms/search/binary-search.ts new file mode 100644 index 00000000..2e8513bf --- /dev/null +++ b/src/ts/algorithms/search/binary-search.ts @@ -0,0 +1,25 @@ +import { Compare, defaultCompare, DOES_NOT_EXIST } from '../../util'; +import { quickSort } from '../sorting/quicksort'; + +export function binarySearch (array: T[], value: T, compareFn = defaultCompare) { + const sortedArray = quickSort(array); + let low = 0; + let high = sortedArray.length - 1; + + while (low <= high) { + const mid = Math.floor((low + high) / 2); + const element = sortedArray[mid]; + // console.log('mid element is ' + element); + if (compareFn(element, value) === Compare.LESS_THAN) { + low = mid + 1; + // console.log('low is ' + low); + } else if (compareFn(element, value) === Compare.BIGGER_THAN) { + high = mid - 1; + // console.log('high is ' + high); + } else { + // console.log('found it'); + return mid; + } + } + return DOES_NOT_EXIST; +} diff --git a/src/ts/algorithms/search/interpolation-search.ts b/src/ts/algorithms/search/interpolation-search.ts new file mode 100644 index 00000000..aebdeb09 --- /dev/null +++ b/src/ts/algorithms/search/interpolation-search.ts @@ -0,0 +1,41 @@ +import { + biggerEquals, + Compare, + defaultCompare, + defaultEquals, + defaultDiff, + DOES_NOT_EXIST, + lesserEquals +} from '../../util'; + +export function interpolationSearch( + array: T[], + value: T, + compareFn = defaultCompare, + equalsFn = defaultEquals, + diffFn = defaultDiff +) { + const { length } = array; + let low = 0; + let high = length - 1; + let position = -1; + let delta = -1; + while ( + low <= high && + biggerEquals(value, array[low], compareFn) && + lesserEquals(value, array[high], compareFn) + ) { + delta = diffFn(value, array[low]) / diffFn(array[high], array[low]); + position = low + Math.floor((high - low) * delta); + if (equalsFn(array[position], value)) { + return position; + } + if (compareFn(array[position], value) === Compare.LESS_THAN) { + low = position + 1; + } else { + high = position - 1; + } + } + + return DOES_NOT_EXIST; +} diff --git a/src/ts/algorithms/search/min-max-search.ts b/src/ts/algorithms/search/min-max-search.ts new file mode 100644 index 00000000..1869f412 --- /dev/null +++ b/src/ts/algorithms/search/min-max-search.ts @@ -0,0 +1,27 @@ +import { defaultCompare, Compare } from '../../util'; + +export function findMaxValue(array: T[], compareFn = defaultCompare) { + if (array && array.length > 0) { + let max = array[0]; + for (let i = 1; i < array.length; i++) { + if (compareFn(max, array[i]) === Compare.LESS_THAN) { + max = array[i]; + } + } + return max; + } + return undefined; +} + +export function findMinValue(array: T[], compareFn = defaultCompare) { + if (array && array.length > 0) { + let min = array[0]; + for (let i = 1; i < array.length; i++) { + if (compareFn(min, array[i]) === Compare.BIGGER_THAN) { + min = array[i]; + } + } + return min; + } + return undefined; +} diff --git a/src/ts/algorithms/search/sequential-search.ts b/src/ts/algorithms/search/sequential-search.ts new file mode 100644 index 00000000..ba9ddf6c --- /dev/null +++ b/src/ts/algorithms/search/sequential-search.ts @@ -0,0 +1,10 @@ +import { defaultEquals, DOES_NOT_EXIST, IEqualsFunction } from '../../util'; + +export function sequentialSearch(array: T[], value: T, equalsFn: IEqualsFunction = defaultEquals) { + for (let i = 0; i < array.length; i++) { + if (equalsFn(value, array[i])) { + return i; + } + } + return DOES_NOT_EXIST; +} diff --git "a/src/ts/algorithms/shuffle/fisher\342\200\223yates.ts" "b/src/ts/algorithms/shuffle/fisher\342\200\223yates.ts" new file mode 100644 index 00000000..b5869692 --- /dev/null +++ "b/src/ts/algorithms/shuffle/fisher\342\200\223yates.ts" @@ -0,0 +1,10 @@ +import { swap } from '../../util'; + +export function shuffle(array: T[]) { + for (let i = array.length - 1; i > 0; i--) { + const randomIndex = Math.floor(Math.random() * (i + 1)); + swap(array, i, randomIndex); + } + + return array; +} diff --git a/src/ts/algorithms/sorting/bubble-sort-improved.ts b/src/ts/algorithms/sorting/bubble-sort-improved.ts new file mode 100644 index 00000000..6e016d4d --- /dev/null +++ b/src/ts/algorithms/sorting/bubble-sort-improved.ts @@ -0,0 +1,18 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +export function modifiedBubbleSort(array: T[], compareFn = defaultCompare) { + const { length } = array; + + for (let i = 0; i < length; i++) { + // console.log('--- '); + for (let j = 0; j < length - 1 - i; j++) { + // console.log('compare ' + array[j] + ' with ' + array[j + 1]); + if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) { + // console.log('swap ' + array[j] + ' with ' + array[j + 1]); + swap(array, j, j + 1); + } + } + } + + return array; +} diff --git a/src/ts/algorithms/sorting/bubble-sort.ts b/src/ts/algorithms/sorting/bubble-sort.ts new file mode 100644 index 00000000..41074f6f --- /dev/null +++ b/src/ts/algorithms/sorting/bubble-sort.ts @@ -0,0 +1,18 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +export function bubbleSort(array: T[], compareFn = defaultCompare) { + const { length } = array; + + for (let i = 0; i < length; i++) { + // console.log('--- '); + for (let j = 0; j < length - 1; j++) { + // console.log('compare ' + array[j] + ' with ' + array[j + 1]); + if (compareFn(array[j], array[j + 1]) === Compare.BIGGER_THAN) { + // console.log('swap ' + array[j] + ' with ' + array[j + 1]); + swap(array, j, j + 1); + } + } + } + + return array; +} diff --git a/src/ts/algorithms/sorting/bucket-sort.ts b/src/ts/algorithms/sorting/bucket-sort.ts new file mode 100644 index 00000000..bcb8f61b --- /dev/null +++ b/src/ts/algorithms/sorting/bucket-sort.ts @@ -0,0 +1,48 @@ +import { insertionSort } from './insertion-sort'; + +function createBuckets(array: number[], bucketSize: number): number[][] { + let minValue = array[0]; + let maxValue = array[0]; + for (let i = 1; i < array.length; i++) { + if (array[i] < minValue) { + minValue = array[i]; + } else if (array[i] > maxValue) { + maxValue = array[i]; + } + } + + const bucketCount = Math.floor((maxValue - minValue) / bucketSize) + 1; + const buckets = []; + for (let i = 0; i < bucketCount; i++) { + buckets[i] = []; + } + + for (let i = 0; i < array.length; i++) { + buckets[Math.floor((array[i] - minValue) / bucketSize)].push(array[i]); + } + + return buckets; +} + +function sortBuckets(buckets: number[][]) { + const sortedArray = []; + for (let i = 0; i < buckets.length; i++) { + if (buckets[i] != null) { + insertionSort(buckets[i]); + + sortedArray.push(...buckets[i]); + } + } + + return sortedArray; +} + +export function bucketSort(array: number[], bucketSize = 5) { + if (array.length < 2) { + return array; + } + + const buckets = createBuckets(array, bucketSize); + + return sortBuckets(buckets); +} diff --git a/src/ts/algorithms/sorting/counting-sort.ts b/src/ts/algorithms/sorting/counting-sort.ts new file mode 100644 index 00000000..be3d9046 --- /dev/null +++ b/src/ts/algorithms/sorting/counting-sort.ts @@ -0,0 +1,30 @@ +import { findMaxValue } from '../search/min-max-search'; + +export function countingSort(array: number[]) { + + if (array.length < 2) { + return array; + } + + const maxValue = findMaxValue(array); + let sortedIndex = 0; + const counts = new Array(maxValue + 1); + + array.forEach(element => { + if (!counts[element]) { + counts[element] = 0; + } + counts[element]++; + }); + + // console.log('Frequencies: ' + counts.join()); + + counts.forEach((element, i) => { + while (element > 0) { + array[sortedIndex++] = i; + element--; + } + }); + + return array; +} diff --git a/src/ts/algorithms/sorting/heap-sort.ts b/src/ts/algorithms/sorting/heap-sort.ts new file mode 100644 index 00000000..7f461860 --- /dev/null +++ b/src/ts/algorithms/sorting/heap-sort.ts @@ -0,0 +1,37 @@ +import { defaultCompare, ICompareFunction, swap } from '../../util'; + +function heapify(array: any[], index: number, heapSize: number, compareFn: ICompareFunction) { + let largest = index; + const left = (2 * index) + 1; + const right = (2 * index) + 2; + + if (left < heapSize && compareFn(array[left], array[index]) > 0) { + largest = left; + } + + if (right < heapSize && compareFn(array[right], array[largest]) > 0) { + largest = right; + } + + if (largest !== index) { + swap(array, index, largest); + heapify(array, largest, heapSize, compareFn); + } +} + +function buildMaxHeap(array: any[], compareFn: ICompareFunction) { + for (let i = Math.floor(array.length / 2); i >= 0; i -= 1) { + heapify(array, i, array.length, compareFn); + } + return array; +} + +export default function heapSort(array: any[], compareFn = defaultCompare) { + let heapSize = array.length; + buildMaxHeap(array, compareFn); + while (heapSize > 1) { + swap(array, 0, --heapSize); + heapify(array, 0, heapSize, compareFn); + } + return array; +} diff --git a/src/ts/algorithms/sorting/insertion-sort.ts b/src/ts/algorithms/sorting/insertion-sort.ts new file mode 100644 index 00000000..e67c4f34 --- /dev/null +++ b/src/ts/algorithms/sorting/insertion-sort.ts @@ -0,0 +1,20 @@ +import { Compare, defaultCompare } from '../../util'; + +export const insertionSort = (array: any[], compareFn = defaultCompare) => { + const { length } = array; + let temp; + for (let i = 1; i < length; i++) { + let j = i; + temp = array[i]; + // console.log('to be inserted ' + temp); + while (j > 0 && compareFn(array[j - 1], temp) === Compare.BIGGER_THAN) { + // console.log('shift ' + array[j - 1]); + array[j] = array[j - 1]; + j--; + } + // console.log('insert ' + temp); + array[j] = temp; + } + + return array; +}; diff --git a/src/ts/algorithms/sorting/merge-sort.ts b/src/ts/algorithms/sorting/merge-sort.ts new file mode 100644 index 00000000..b4f20f65 --- /dev/null +++ b/src/ts/algorithms/sorting/merge-sort.ts @@ -0,0 +1,25 @@ +import { Compare, defaultCompare, ICompareFunction } from '../../util'; + +function merge(left: T[], right: T[], compareFn: ICompareFunction) { + let i = 0; + let j = 0; + const result = []; + + while (i < left.length && j < right.length) { + result.push(compareFn(left[i], right[j]) === Compare.LESS_THAN ? left[i++] : right[j++]); + } + + return result.concat(i < left.length ? left.slice(i) : right.slice(j)); +} + +export function mergeSort(array: T[], compareFn = defaultCompare): T[] { + if (array.length > 1) { + const { length } = array; + const middle = Math.floor(length / 2); + const left = mergeSort(array.slice(0, middle), compareFn); + const right = mergeSort(array.slice(middle, length), compareFn); + array = merge(left, right, compareFn); + } + + return array; +} diff --git a/src/ts/algorithms/sorting/quicksort.ts b/src/ts/algorithms/sorting/quicksort.ts new file mode 100644 index 00000000..f9336b19 --- /dev/null +++ b/src/ts/algorithms/sorting/quicksort.ts @@ -0,0 +1,56 @@ +import { Compare, defaultCompare, ICompareFunction, swap } from '../../util'; + +const partition = function(array: any[], left: number, right: number, compareFn: ICompareFunction) { + const pivot = array[Math.floor((right + left) / 2)]; + let i = left; + let j = right; + + // console.log('pivot is ' + pivot + '; left is ' + left + '; right is ' + right); + + while (i <= j) { + while (compareFn(array[i], pivot) === Compare.LESS_THAN) { + i++; + // console.log('i = ' + i); + } + + while (compareFn(array[j], pivot) === Compare.BIGGER_THAN) { + j--; + // console.log('j = ' + j); + } + + if (i <= j) { + // console.log('swap ' + array[i] + ' with ' + array[j]); + swap(array, i, j); + i++; + j--; + } + } + + return i; +}; + +const quick = function( + array: any[], + left: number, + right: number, + compareFn: ICompareFunction +) { + let index; + + if (array.length > 1) { + index = partition(array, left, right, compareFn); + + if (left < index - 1) { + quick(array, left, index - 1, compareFn); + } + + if (index < right) { + quick(array, index, right, compareFn); + } + } + return array; +}; + +export const quickSort = (array: any[], compareFn = defaultCompare) => { + return quick(array, 0, array.length - 1, compareFn); +}; diff --git a/src/ts/algorithms/sorting/radix-sort.ts b/src/ts/algorithms/sorting/radix-sort.ts new file mode 100644 index 00000000..e6d1027a --- /dev/null +++ b/src/ts/algorithms/sorting/radix-sort.ts @@ -0,0 +1,60 @@ +import { findMaxValue, findMinValue } from '../search/min-max-search'; + +const countingSortForRadix = ( + array: number[], + radixBase: number, + significantDigit: number, + minValue: any +) => { + let bucketsIndex; + const buckets: number[] = []; + const aux: number[] = []; + + for (let i = 0; i < radixBase; i++) { + buckets[i] = 0; + } + + for (let i = 0; i < array.length; i++) { + bucketsIndex = Math.floor(((array[i] - minValue) / significantDigit) % radixBase); + buckets[bucketsIndex]++; + } + + for (let i = 1; i < radixBase; i++) { + buckets[i] += buckets[i - 1]; + } + + for (let i = array.length - 1; i >= 0; i--) { + bucketsIndex = Math.floor(((array[i] - minValue) / significantDigit) % radixBase); + aux[--buckets[bucketsIndex]] = array[i]; + } + + + // array = []; + // array.push(...aux); + for (let i = 0; i < array.length; i++) { + array[i] = aux[i]; + } + + return array; +}; + +export function radixSort(array: number[], radixBase = 10) { + + if (array.length < 2) { + return array; + } + + const minValue = findMinValue(array); + const maxValue = findMaxValue(array); + + // Perform counting sort for each significant digit, starting at 1 + let significantDigit = 1; + while ((maxValue - minValue) / significantDigit >= 1) { + // console.log('radix sort for digit ' + significantDigit); + array = countingSortForRadix(array, radixBase, significantDigit, minValue); + // console.log(array.join()); + significantDigit *= radixBase; + } + + return array; +} diff --git a/src/ts/algorithms/sorting/selection-sort.ts b/src/ts/algorithms/sorting/selection-sort.ts new file mode 100644 index 00000000..465e78a1 --- /dev/null +++ b/src/ts/algorithms/sorting/selection-sort.ts @@ -0,0 +1,23 @@ +import { Compare, defaultCompare, swap } from '../../util'; + +export const selectionSort = (array: any[], compareFn = defaultCompare) => { + const { length } = array; + let indexMin; + + for (let i = 0; i < length - 1; i++) { + indexMin = i; + // console.log('index ' + array[i]); + for (let j = i; j < length; j++) { + if (compareFn(array[indexMin], array[j]) === Compare.BIGGER_THAN) { + // console.log('new index min ' + array[j]); + indexMin = j; + } + } + if (i !== indexMin) { + // console.log('swap ' + array[i] + ' with ' + array[indexMin]); + swap(array, i, indexMin); + } + } + + return array; +}; diff --git a/src/ts/algorithms/sorting/shell-sort.ts b/src/ts/algorithms/sorting/shell-sort.ts new file mode 100644 index 00000000..19e11bf9 --- /dev/null +++ b/src/ts/algorithms/sorting/shell-sort.ts @@ -0,0 +1,25 @@ +import { Compare, defaultCompare } from '../../util'; + +export function shellSort(array: T[], compareFn = defaultCompare) { + let increment = array.length / 2; + while (increment > 0) { + for (let i = increment; i < array.length; i++) { + let j = i; + const temp = array[i]; + + while (j >= increment && compareFn(array[j - increment], temp) === Compare.BIGGER_THAN) { + array[j] = array[j - increment]; + j = j - increment; + } + + array[j] = temp; + } + + if (increment === 2) { + increment = 1; + } else { + increment = Math.floor(increment * 5 / 11); + } + } + return array; +} diff --git a/src/ts/algorithms/string/brute-force.ts b/src/ts/algorithms/string/brute-force.ts new file mode 100644 index 00000000..1bf21f85 --- /dev/null +++ b/src/ts/algorithms/string/brute-force.ts @@ -0,0 +1,22 @@ +const stringSearch = (text: string, pattern: string) => { + const n = text.length; + const m = pattern.length; + + if (m > n) { + return -1; + } + + for (let i = 0; i < n; i++) { + let j = 0; + for (j = 0; j < m && (i + j) < n; j++) { + if (text.charAt(i + j) !== pattern.charAt(j)) { + break; + } + } + if (j === m) { + return i; + } + } + + return -1; +}; diff --git a/src/ts/algorithms/string/huffman.ts b/src/ts/algorithms/string/huffman.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/ts/algorithms/string/knuth-morris-pratt.ts b/src/ts/algorithms/string/knuth-morris-pratt.ts new file mode 100644 index 00000000..4b0f2759 --- /dev/null +++ b/src/ts/algorithms/string/knuth-morris-pratt.ts @@ -0,0 +1,46 @@ +const buildTable = (pattern: string) => { + const length = pattern.length; + const table = []; + let position = 2; + let cnd = 0; + + table[0] = -1; + table[1] = 0; + + while (position < length) { + if (pattern[position - 1] === pattern[cnd]) { + table[position++] = ++cnd; + } else if (cnd > 0) { + cnd = table[cnd]; + } else { + table[position++] = 0; + } + } + + return table; +}; + +const knuthMorrisPratt = (text: string, pattern: string) => { + const textLength = text.length; + const patternLength = pattern.length; + let m = 0; + let i = 0; + const table = buildTable(pattern); + + while (m + i < textLength) { + if (pattern[i] === text[m + i]) { + if (i === patternLength - 1) { + return m; + } + i++; + } else if (table[i] >= 0) { + i = table[i]; + m = m + i - table[i]; + } else { + i = 0; + m++; + } + } + + return textLength; +}; diff --git a/src/ts/algorithms/string/longest-common-substring.ts b/src/ts/algorithms/string/longest-common-substring.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/ts/algorithms/string/rabin-karp.ts b/src/ts/algorithms/string/rabin-karp.ts new file mode 100644 index 00000000..ab60fe3e --- /dev/null +++ b/src/ts/algorithms/string/rabin-karp.ts @@ -0,0 +1,39 @@ +const base = 997; + +const hash = (word: string) => { + let h = 0; + + for (let i = 0; i < word.length; i++) { + h += word.charCodeAt(i) * Math.pow(base, word.length - i - 1); + } + + return h; +}; + +const rabinKarp = (text: string, pattern: string) => { + if (pattern == null || pattern.length === 0) { + return 0; + } + + const hashPattern = hash(pattern); + let currentSubstring = text.substring(0, pattern.length); + let hashCurrentSubstring; + + for (let i = pattern.length; i <= text.length; i++) { + if (hashCurrentSubstring === undefined) { + hashCurrentSubstring = hash(currentSubstring); + } else { + hashCurrentSubstring -= currentSubstring.charCodeAt(0) * Math.pow(base, pattern.length - 1); + hashCurrentSubstring *= base; + hashCurrentSubstring += text.charCodeAt(i); + + currentSubstring = currentSubstring.substring(1) + text[i]; + } + + if (hashPattern === hashCurrentSubstring && pattern === currentSubstring) { + return i === pattern.length ? 0 : i - pattern.length + 1; + } + } + + return -1; +}; diff --git a/src/ts/data-structures/avl-tree.ts b/src/ts/data-structures/avl-tree.ts new file mode 100644 index 00000000..feb44a19 --- /dev/null +++ b/src/ts/data-structures/avl-tree.ts @@ -0,0 +1,201 @@ +import { Compare, defaultCompare, ICompareFunction } from '../util'; +import BinarySearchTree from './binary-search-tree'; +import { Node } from './models/node'; + +enum BalanceFactor { + UNBALANCED_RIGHT = 1, + SLIGHTLY_UNBALANCED_RIGHT = 2, + BALANCED = 3, + SLIGHTLY_UNBALANCED_LEFT = 4, + UNBALANCED_LEFT = 5 +} + +export default class AVLTree extends BinarySearchTree { + + constructor(protected compareFn: ICompareFunction = defaultCompare) { + super(compareFn); + } + + private getNodeHeight(node: Node): number { + if (node == null) { + return -1; + } + return Math.max(this.getNodeHeight(node.left), this.getNodeHeight(node.right)) + 1; + } + + /** + * Left left case: rotate right + * + * b a + * / \ / \ + * a e -> rotationLL(b) -> c b + * / \ / \ + * c d d e + * + * @param node Node + */ + private rotationLL(node: Node) { + const tmp = node.left; + node.left = tmp.right; + tmp.right = node; + return tmp; + } + + /** + * Right right case: rotate left + * + * a b + * / \ / \ + * c b -> rotationRR(a) -> a e + * / \ / \ + * d e c d + * + * @param node Node + */ + private rotationRR(node: Node) { + const tmp = node.right; + node.right = tmp.left; + tmp.left = node; + return tmp; + } + + /** + * Left right case: rotate left then right + * @param node Node + */ + private rotationLR(node: Node) { + node.left = this.rotationRR(node.left); + return this.rotationLL(node); + } + + /** + * Right left case: rotate right then left + * @param node Node + */ + private rotationRL(node: Node) { + node.right = this.rotationLL(node.right); + return this.rotationRR(node); + } + + private getBalanceFactor(node: Node) { + const heightDifference = this.getNodeHeight(node.left) - this.getNodeHeight(node.right); + switch (heightDifference) { + case -2: + return BalanceFactor.UNBALANCED_RIGHT; + case -1: + return BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT; + case 1: + return BalanceFactor.SLIGHTLY_UNBALANCED_LEFT; + case 2: + return BalanceFactor.UNBALANCED_LEFT; + default: + return BalanceFactor.BALANCED; + } + } + + insert(key: T) { + this.root = this.insertNode(this.root, key); + } + + protected insertNode(node: Node, key: T) { + if (node == null) { + return new Node(key); + } else if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + node.left = this.insertNode(node.left, key); + } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + node.right = this.insertNode(node.right, key); + } else { + return node; // duplicated key + } + + // verify if tree is balanced + const balanceState = this.getBalanceFactor(node); + + if (balanceState === BalanceFactor.UNBALANCED_LEFT) { + if (this.compareFn(key, node.left.key) === Compare.LESS_THAN) { + // Left left case + node = this.rotationLL(node); + } else { + // Left right case + return this.rotationLR(node); + } + } + + if (balanceState === BalanceFactor.UNBALANCED_RIGHT) { + if (this.compareFn(key, node.right.key) === Compare.BIGGER_THAN) { + // Right right case + node = this.rotationRR(node); + } else { + // Right left case + return this.rotationRL(node); + } + } + + return node; + } + + protected removeNode(node: Node, key: T) { + if (node == null) { + return null; + } + + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + // The key to be deleted is in the left sub-tree + node.left = this.removeNode(node.left, key); + } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + // The key to be deleted is in the right sub-tree + node.right = this.removeNode(node.right, key); + } else { + // node is the node to be deleted + if (node.left == null && node.right == null) { + node = null; + } else if (node.left == null && node.right != null) { + node = node.right; + } else if (node.left != null && node.right == null) { + node = node.left; + } else { + // node has 2 children, get the in-order successor + const inOrderSuccessor = this.minNode(node.right); + node.key = inOrderSuccessor.key; + node.right = this.removeNode(node.right, inOrderSuccessor.key); + } + } + + if (node == null) { + return node; + } + + // verify if tree is balanced + const balanceState = this.getBalanceFactor(node); + + if (balanceState === BalanceFactor.UNBALANCED_LEFT) { + // Left left case + if ( + this.getBalanceFactor(node.left) === BalanceFactor.BALANCED || + this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT + ) { + return this.rotationLL(node); + } + // Left right case + if (this.getBalanceFactor(node.left) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT) { + return this.rotationLR(node.left); + } + } + + if (balanceState === BalanceFactor.UNBALANCED_RIGHT) { + // Right right case + if ( + this.getBalanceFactor(node.right) === BalanceFactor.BALANCED || + this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_RIGHT + ) { + return this.rotationRR(node); + } + // Right left case + if (this.getBalanceFactor(node.right) === BalanceFactor.SLIGHTLY_UNBALANCED_LEFT) { + return this.rotationRL(node.right); + } + } + + return node; + } +} diff --git a/src/ts/data-structures/binary-search-tree.ts b/src/ts/data-structures/binary-search-tree.ts new file mode 100644 index 00000000..dd7141ff --- /dev/null +++ b/src/ts/data-structures/binary-search-tree.ts @@ -0,0 +1,159 @@ +import { Compare, defaultCompare, ICompareFunction } from '../util'; +import { Node } from './models/node'; + +export default class BinarySearchTree { + protected root: Node; + + constructor(protected compareFn: ICompareFunction = defaultCompare) {} + + insert(key: T) { + // special case: first key + if (this.root == null) { + this.root = new Node(key); + } else { + this.insertNode(this.root, key); + } + } + + protected insertNode(node: Node, key: T) { + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + if (node.left == null) { + node.left = new Node(key); + } else { + this.insertNode(node.left, key); + } + } else if (node.right == null) { + node.right = new Node(key); + } else { + this.insertNode(node.right, key); + } + } + + getRoot() { + return this.root; + } + + search(key: T) { + return this.searchNode(this.root, key); + } + + private searchNode(node: Node, key: T): boolean { + if (node == null) { + return false; + } + + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + return this.searchNode(node.left, key); + } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + return this.searchNode(node.right, key); + } + // key is equal to node.item + return true; + } + + inOrderTraverse(callback: Function) { + this.inOrderTraverseNode(this.root, callback); + } + + private inOrderTraverseNode(node: Node, callback: Function) { + if (node != null) { + this.inOrderTraverseNode(node.left, callback); + callback(node.key); + this.inOrderTraverseNode(node.right, callback); + } + } + + preOrderTraverse(callback: Function) { + this.preOrderTraverseNode(this.root, callback); + } + + private preOrderTraverseNode(node: Node, callback: Function) { + if (node != null) { + callback(node.key); + this.preOrderTraverseNode(node.left, callback); + this.preOrderTraverseNode(node.right, callback); + } + } + + postOrderTraverse(callback: Function) { + this.postOrderTraverseNode(this.root, callback); + } + + private postOrderTraverseNode(node: Node, callback: Function) { + if (node != null) { + this.postOrderTraverseNode(node.left, callback); + this.postOrderTraverseNode(node.right, callback); + callback(node.key); + } + } + + min() { + return this.minNode(this.root); + } + + protected minNode(node: Node) { + let current = node; + while (current != null && current.left != null) { + current = current.left; + } + return current; + } + + max() { + return this.maxNode(this.root); + } + + protected maxNode(node: Node) { + let current = node; + while (current != null && current.right != null) { + current = current.right; + } + return current; + } + + remove(key: T) { + this.root = this.removeNode(this.root, key); + } + + protected removeNode(node: Node, key: T) { + if (node == null) { + return null; + } + + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + node.left = this.removeNode(node.left, key); + return node; + } else if (this.compareFn(key, node.key) === Compare.BIGGER_THAN) { + node.right = this.removeNode(node.right, key); + return node; + } else { + // key is equal to node.item + + // handle 3 special conditions + // 1 - a leaf node + // 2 - a node with only 1 child + // 3 - a node with 2 children + + // case 1 + if (node.left == null && node.right == null) { + node = null; + return node; + } + + // case 2 + if (node.left == null) { + node = node.right; + return node; + } else if (node.right == null) { + node = node.left; + return node; + } + + // case 3 + const aux = this.minNode(node.right); + node.key = aux.key; + node.right = this.removeNode(node.right, aux.key); + return node; + } + } +} diff --git a/src/ts/data-structures/circular-linked-list.ts b/src/ts/data-structures/circular-linked-list.ts new file mode 100644 index 00000000..f422d276 --- /dev/null +++ b/src/ts/data-structures/circular-linked-list.ts @@ -0,0 +1,80 @@ +import { defaultEquals, IEqualsFunction } from '../util'; +import LinkedList from './linked-list'; +import { Node } from './models/linked-list-models'; + +export default class CircularLinkedList extends LinkedList { + constructor(protected equalsFn: IEqualsFunction = defaultEquals) { + super(equalsFn); + } + + push(element: T) { + const node = new Node(element); + let current; + + if (this.head == null) { + this.head = node; + } else { + current = this.getElementAt(this.size() - 1); + current.next = node; + } + + // set node.next to head - to have circular list + node.next = this.head; + + this.count++; + } + + insert(element: T, index: number) { + if (index >= 0 && index <= this.count) { + const node = new Node(element); + let current = this.head; + + if (index === 0) { + if (this.head == null) { + // if no node in list + this.head = node; + node.next = this.head; + } else { + node.next = current; + current = this.getElementAt(this.size()); + // update last element + this.head = node; + current.next = this.head; + } + } else { + const previous = this.getElementAt(index - 1); + node.next = previous.next; + previous.next = node; + } + this.count++; + return true; + } + return false; + } + + removeAt(index: number) { + if (index >= 0 && index < this.count) { + let current = this.head; + + if (index === 0) { + if (this.size() === 1) { + this.head = undefined; + } else { + const removed = this.head; + current = this.getElementAt(this.size() - 1); + this.head = this.head.next; + current.next = this.head; + current = removed; + } + } else { + // no need to update last element for circular list + const previous = this.getElementAt(index - 1); + current = previous.next; + previous.next = current.next; + } + this.count--; + return current.element; + } + return undefined; + } +} diff --git a/src/ts/data-structures/deque.ts b/src/ts/data-structures/deque.ts new file mode 100644 index 00000000..155b735c --- /dev/null +++ b/src/ts/data-structures/deque.ts @@ -0,0 +1,90 @@ +export default class Deque { + private count: number; + private lowestCount: number; + private items: any; + + constructor() { + this.count = 0; + this.lowestCount = 0; + this.items = {}; + } + + addFront(element: T) { + if (this.isEmpty()) { + this.addBack(element); + } else if (this.lowestCount > 0) { + this.lowestCount--; + this.items[this.lowestCount] = element; + } else { + for (let i = this.count; i > 0; i--) { + this.items[i] = this.items[i - 1]; + } + this.count++; + this.items[0] = element; + } + } + + addBack(element: T) { + this.items[this.count] = element; + this.count++; + } + + removeFront() { + if (this.isEmpty()) { + return undefined; + } + const result = this.items[this.lowestCount]; + delete this.items[this.lowestCount]; + this.lowestCount++; + return result; + } + + removeBack() { + if (this.isEmpty()) { + return undefined; + } + this.count--; + const result = this.items[this.count]; + delete this.items[this.count]; + return result; + } + + peekFront() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.lowestCount]; + } + + peekBack() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.count - 1]; + } + + isEmpty() { + return this.size() === 0; + } + + clear() { + this.items = {}; + this.count = 0; + this.lowestCount = 0; + } + + size() { + return this.count - this.lowestCount; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + let objString = `${this.items[this.lowestCount]}`; + for (let i = this.lowestCount + 1; i < this.count; i++) { + objString = `${objString},${this.items[i]}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/dictionary.ts b/src/ts/data-structures/dictionary.ts new file mode 100644 index 00000000..98485718 --- /dev/null +++ b/src/ts/data-structures/dictionary.ts @@ -0,0 +1,86 @@ +import { defaultToString } from '../util'; +import { ValuePair } from './models/value-pair'; + +export default class Dictionary { + private table: { [key: string]: ValuePair }; + + constructor(private toStrFn: (key: K) => string = defaultToString) { + this.table = {}; + } + + set(key: K, value: V) { + if (key != null && value != null) { + const tableKey = this.toStrFn(key); + this.table[tableKey] = new ValuePair(key, value); + return true; + } + return false; + } + + get(key: K): V { + const valuePair = this.table[this.toStrFn(key)]; + return valuePair == null ? undefined : valuePair.value; + } + + hasKey(key: K) { + return this.table[this.toStrFn(key)] != null; + } + + remove(key: K) { + if (this.hasKey(key)) { + delete this.table[this.toStrFn(key)]; + return true; + } + return false; + } + + values(): V[] { + return this.keyValues().map( + (valuePair: ValuePair) => valuePair.value + ); + } + + keys(): K[] { + return this.keyValues().map( + (valuePair: ValuePair) => valuePair.key + ); + } + + keyValues(): ValuePair[] { + return Object.values(this.table); + } + + forEach(callbackFn: (key: K, value: V) => any) { + const valuePairs = this.keyValues(); + for (let i = 0; i < valuePairs.length; i++) { + const result = callbackFn(valuePairs[i].key, valuePairs[i].value); + if (result === false) { + break; + } + } + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.table).length; + } + + clear() { + this.table = {}; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const valuePairs = this.keyValues(); + let objString = `${valuePairs[0].toString()}`; + for (let i = 1; i < valuePairs.length; i++) { + objString = `${objString},${valuePairs[i].toString()}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/doubly-linked-list.ts b/src/ts/data-structures/doubly-linked-list.ts new file mode 100644 index 00000000..a2d16e72 --- /dev/null +++ b/src/ts/data-structures/doubly-linked-list.ts @@ -0,0 +1,148 @@ +import { defaultEquals, IEqualsFunction } from '../util'; +import LinkedList from './linked-list'; +import { DoublyNode } from './models/linked-list-models'; + +export default class DoublyLinkedList extends LinkedList { + protected head: DoublyNode | undefined; + protected tail: DoublyNode | undefined; + + constructor(protected equalsFn: IEqualsFunction = defaultEquals) { + super(equalsFn); + } + + push(element: T) { + const node = new DoublyNode(element); + + if (this.head == null) { + this.head = node; + this.tail = node; // NEW + } else { + // attach to the tail node // NEW + this.tail.next = node; + node.prev = this.tail; + this.tail = node; + } + this.count++; + } + + insert(element: T, index: number) { + if (index >= 0 && index <= this.count) { + const node = new DoublyNode(element); + let current = this.head; + + if (index === 0) { + if (this.head == null) { + // NEW + this.head = node; + this.tail = node; + } else { + node.next = this.head; + this.head.prev = node; // NEW + this.head = node; + } + } else if (index === this.count) { + // last item // NEW + current = this.tail; // {2} + current.next = node; + node.prev = current; + this.tail = node; + } else { + const previous = this.getElementAt(index - 1); + current = previous.next; + node.next = current; + previous.next = node; + + current.prev = node; // NEW + node.prev = previous; // NEW + } + this.count++; + return true; + } + return false; + } + + removeAt(index: number) { + if (index >= 0 && index < this.count) { + let current = this.head; + + if (index === 0) { + this.head = this.head.next; // {1} + // if there is only one item, then we update tail as well //NEW + if (this.count === 1) { + // {2} + this.tail = undefined; + } else { + this.head.prev = undefined; // {3} + } + } else if (index === this.count - 1) { + // last item //NEW + current = this.tail; // {4} + this.tail = current.prev; + this.tail.next = undefined; + } else { + current = this.getElementAt(index); + const previous = current.prev; + // link previous with current's next - skip it to remove + previous.next = current.next; // {6} + current.next.prev = previous; // NEW + } + this.count--; + return current.element; + } + return undefined; + } + + indexOf(element: T) { + let current = this.head; + let index = 0; + + while (current != null) { + if (this.equalsFn(element, current.element)) { + return index; + } + index++; + current = current.next; + } + + return -1; + } + + getHead() { + return this.head; + } + + getTail() { + return this.tail; + } + + clear() { + super.clear(); + this.tail = undefined; + } + + toString() { + if (this.head == null) { + return ''; + } + let objString = `${this.head.element}`; + let current = this.head.next; + while (current != null) { + objString = `${objString},${current.element}`; + current = current.next; + } + return objString; + } + + inverseToString() { + if (this.tail == null) { + return ''; + } + let objString = `${this.tail.element}`; + let previous = this.tail.prev; + while (previous != null) { + objString = `${objString},${previous.element}`; + previous = previous.prev; + } + return objString; + } +} diff --git a/src/ts/data-structures/graph.ts b/src/ts/data-structures/graph.ts new file mode 100644 index 00000000..b07a4eb4 --- /dev/null +++ b/src/ts/data-structures/graph.ts @@ -0,0 +1,49 @@ +import Dictionary from './dictionary'; + +export default class Graph { + private vertices: (string | number)[] = []; + private adjList: Dictionary = new Dictionary(); + + constructor(private isDirected = false) {} + + addVertex(v: string | number) { + if (!this.vertices.includes(v)) { + this.vertices.push(v); + this.adjList.set(v, []); // initialize adjacency list with array as well; + } + } + + addEdge(a: string | number, b: string | number) { + if (!this.adjList.get(a)) { + this.addVertex(a); + } + if (!this.adjList.get(b)) { + this.addVertex(b); + } + this.adjList.get(a).push(b); + if (this.isDirected !== true) { + this.adjList.get(b).push(a); + } + } + + getVertices() { + return this.vertices; + } + + getAdjList() { + return this.adjList; + } + + toString() { + let s = ''; + for (let i = 0; i < this.vertices.length; i++) { + s += this.vertices[i] + ' -> '; + const neighbors = this.adjList.get(this.vertices[i]); + for (let j = 0; j < neighbors.length; j++) { + s += neighbors[j] + ' '; + } + s += '\n'; + } + return s; + } +} diff --git a/src/ts/data-structures/hash-table-linear-probing-lazy.ts b/src/ts/data-structures/hash-table-linear-probing-lazy.ts new file mode 100644 index 00000000..43817050 --- /dev/null +++ b/src/ts/data-structures/hash-table-linear-probing-lazy.ts @@ -0,0 +1,136 @@ +import { defaultToString } from '../util'; +import { ValuePairLazy } from './models/value-pair-lazy'; + +export default class HashTableLinearProbingLazy { + protected table: { [key: string]: ValuePairLazy }; + + constructor(protected toStrFn: (key: K) => string = defaultToString) { + this.table = {}; + } + + private loseloseHashCode(key: K) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + hashCode(key: K) { + return this.loseloseHashCode(key); + } + + put(key: K, value: V) { + if (key != null && value != null) { + const position = this.hashCode(key); + + if ( + this.table[position] == null || + (this.table[position] != null && this.table[position].isDeleted) + ) { + this.table[position] = new ValuePairLazy(key, value); + } else { + let index = position + 1; + while (this.table[index] != null && !this.table[position].isDeleted) { + index++; + } + this.table[index] = new ValuePairLazy(key, value); + } + return true; + } + return false; + } + + get(key: K) { + const position = this.hashCode(key); + + if (this.table[position] != null) { + if (this.table[position].key === key && !this.table[position].isDeleted) { + return this.table[position].value; + } + let index = position + 1; + while ( + this.table[index] != null && + (this.table[index].key !== key || this.table[index].isDeleted) + ) { + if (this.table[index].key === key && this.table[index].isDeleted) { + return undefined; + } + index++; + } + if ( + this.table[index] != null && + this.table[index].key === key && + !this.table[index].isDeleted + ) { + return this.table[position].value; + } + } + return undefined; + } + + remove(key: K) { + const position = this.hashCode(key); + + if (this.table[position] != null) { + if (this.table[position].key === key && !this.table[position].isDeleted) { + this.table[position].isDeleted = true; + return true; + } + let index = position + 1; + while ( + this.table[index] != null && + (this.table[index].key !== key || this.table[index].isDeleted) + ) { + index++; + } + if ( + this.table[index] != null && + this.table[index].key === key && + !this.table[index].isDeleted + ) { + this.table[index].isDeleted = true; + return true; + } + } + return false; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + let count = 0; + Object.values(this.table).forEach(valuePair => { + count += valuePair.isDeleted === true ? 0 : 1; + }); + return count; + } + + clear() { + this.table = {}; + } + + getTable() { + return this.table; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[ + keys[i] + ].toString()}}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/hash-table-linear-probing.ts b/src/ts/data-structures/hash-table-linear-probing.ts new file mode 100644 index 00000000..872b4421 --- /dev/null +++ b/src/ts/data-structures/hash-table-linear-probing.ts @@ -0,0 +1,128 @@ +import { defaultToString } from '../util'; +import { ValuePair } from './models/value-pair'; + +export default class HashTableLinearProbing { + protected table: { [key: string]: ValuePair }; + + constructor(protected toStrFn: (key: K) => string = defaultToString) { + this.table = {}; + } + + private loseloseHashCode(key: K) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + hashCode(key: K) { + return this.loseloseHashCode(key); + } + + put(key: K, value: V) { + if (key != null && value != null) { + const position = this.hashCode(key); + + if (this.table[position] == null) { + this.table[position] = new ValuePair(key, value); + } else { + let index = position + 1; + while (this.table[index] != null) { + index++; + } + this.table[index] = new ValuePair(key, value); + } + return true; + } + return false; + } + + get(key: K) { + const position = this.hashCode(key); + + if (this.table[position] != null) { + if (this.table[position].key === key) { + return this.table[position].value; + } + let index = position + 1; + while (this.table[index] != null && this.table[index].key !== key) { + index++; + } + if (this.table[index] != null && this.table[index].key === key) { + return this.table[position].value; + } + } + return undefined; + } + + remove(key: K) { + const position = this.hashCode(key); + + if (this.table[position] != null) { + if (this.table[position].key === key) { + delete this.table[position]; + this.verifyRemoveSideEffect(key, position); + return true; + } + let index = position + 1; + while (this.table[index] != null && this.table[index].key !== key) { + index++; + } + if (this.table[index] != null && this.table[index].key === key) { + delete this.table[index]; + this.verifyRemoveSideEffect(key, index); + return true; + } + } + return false; + } + + private verifyRemoveSideEffect(key: K, removedPosition: number) { + const hash = this.hashCode(key); + let index = removedPosition + 1; + while (this.table[index] != null) { + const posHash = this.hashCode(this.table[index].key); + if (posHash <= hash || posHash <= removedPosition) { + this.table[removedPosition] = this.table[index]; + delete this.table[index]; + removedPosition = index; + } + index++; + } + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.table).length; + } + + clear() { + this.table = {}; + } + + getTable() { + return this.table; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[ + keys[i] + ].toString()}}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/hash-table-separate-chaining.ts b/src/ts/data-structures/hash-table-separate-chaining.ts new file mode 100644 index 00000000..165ff15d --- /dev/null +++ b/src/ts/data-structures/hash-table-separate-chaining.ts @@ -0,0 +1,106 @@ +import { defaultToString } from '../util'; +import LinkedList from './linked-list'; +import { ValuePair } from './models/value-pair'; + +export default class HashTableSeparateChaining { + protected table: { [key: string]: LinkedList> }; + + constructor(protected toStrFn: (key: K) => string = defaultToString) { + this.table = {}; + } + + private loseloseHashCode(key: K) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + hashCode(key: K) { + return this.loseloseHashCode(key); + } + + put(key: K, value: V) { + if (key != null && value != null) { + const position = this.hashCode(key); + + if (this.table[position] == null) { + this.table[position] = new LinkedList>(); + } + this.table[position].push(new ValuePair(key, value)); + return true; + } + return false; + } + + get(key: K) { + const position = this.hashCode(key); + const linkedList = this.table[position]; + if (linkedList != null && !linkedList.isEmpty()) { + let current = linkedList.getHead(); + while (current != null) { + if (current.element.key === key) { + return current.element.value; + } + current = current.next; + } + } + return undefined; + } + + remove(key: K) { + const position = this.hashCode(key); + const linkedList = this.table[position]; + if (linkedList != null && !linkedList.isEmpty()) { + let current = linkedList.getHead(); + while (current != null) { + if (current.element.key === key) { + linkedList.remove(current.element); + if (linkedList.isEmpty()) { + delete this.table[position]; + } + return true; + } + current = current.next; + } + } + return false; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + let count = 0; + Object.values(this.table).forEach(linkedList => count += linkedList.size()); + return count; + } + + clear() { + this.table = {}; + } + + getTable() { + return this.table; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[ + keys[i] + ].toString()}}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/hash-table.ts b/src/ts/data-structures/hash-table.ts new file mode 100644 index 00000000..7b3c6983 --- /dev/null +++ b/src/ts/data-structures/hash-table.ts @@ -0,0 +1,87 @@ +import { defaultToString } from '../util'; +import { ValuePair } from './models/value-pair'; + +export default class HashTable { + protected table: { [key: string]: ValuePair }; + + constructor(protected toStrFn: (key: K) => string = defaultToString) { + this.table = {}; + } + + private loseloseHashCode(key: K) { + if (typeof key === 'number') { + return key; + } + const tableKey = this.toStrFn(key); + let hash = 0; + for (let i = 0; i < tableKey.length; i++) { + hash += tableKey.charCodeAt(i); + } + return hash % 37; + } + + /* private djb2HashCode(key: K) { + const tableKey = this.toStrFn(key); + let hash = 5381; + for (let i = 0; i < tableKey.length; i++) { + hash = (hash * 33) + tableKey.charCodeAt(i); + } + return hash % 1013; + } */ + + hashCode(key: K) { + return this.loseloseHashCode(key); + } + + put(key: K, value: V) { + if (key != null && value != null) { + const position = this.hashCode(key); + this.table[position] = new ValuePair(key, value); + return true; + } + return false; + } + + get(key: K) { + const valuePair = this.table[this.hashCode(key)]; + return valuePair == null ? undefined : valuePair.value; + } + + remove(key: K) { + const hash = this.hashCode(key); + const valuePair = this.table[hash]; + if (valuePair != null) { + delete this.table[hash]; + return true; + } + return false; + } + + getTable() { + return this.table; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.table).length; + } + + clear() { + this.table = {}; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const keys = Object.keys(this.table); + let objString = `{${keys[0]} => ${this.table[keys[0]].toString()}}`; + for (let i = 1; i < keys.length; i++) { + objString = `${objString},{${keys[i]} => ${this.table[keys[i]].toString()}}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/heap.ts b/src/ts/data-structures/heap.ts new file mode 100644 index 00000000..5f27b089 --- /dev/null +++ b/src/ts/data-structures/heap.ts @@ -0,0 +1,121 @@ +import { Compare, defaultCompare, ICompareFunction, reverseCompare, swap } from '../util'; + +export class MinHeap { + protected heap: T[] = []; + + constructor(protected compareFn: ICompareFunction = defaultCompare) {} + + private getLeftIndex(index: number) { + return 2 * index + 1; + } + + private getRightIndex(index: number) { + return 2 * index + 2; + } + + private getParentIndex(index: number) { + if (index === 0) { + return undefined; + } + return Math.floor((index - 1) / 2); + } + + size() { + return this.heap.length; + } + + isEmpty() { + return this.size() <= 0; + } + + clear() { + this.heap = []; + } + + findMinimum() { + return this.isEmpty() ? undefined : this.heap[0]; + } + + insert(value: T) { + if (value != null) { + const index = this.heap.length; + this.heap.push(value); + this.siftUp(index); + return true; + } + return false; + } + + private siftDown(index: number) { + let element = index; + const left = this.getLeftIndex(index); + const right = this.getRightIndex(index); + const size = this.size(); + + if (left < size && this.compareFn(this.heap[element], this.heap[left]) === Compare.BIGGER_THAN) { + element = left; + } + + if ( + right < size && + this.compareFn(this.heap[element], this.heap[right]) === Compare.BIGGER_THAN + ) { + element = right; + } + + if (index !== element) { + swap(this.heap, index, element); + this.siftDown(element); + } + } + + private siftUp(index: number): void { + let parent = this.getParentIndex(index); + while ( + index > 0 && + this.compareFn(this.heap[parent], this.heap[index]) === Compare.BIGGER_THAN + ) { + swap(this.heap, parent, index); + index = parent; + parent = this.getParentIndex(index); + } + } + + extract() { + if (this.isEmpty()) { + return undefined; + } + if (this.size() === 1) { + return this.heap.shift(); + } + const removedValue = this.heap[0]; + this.heap[0] = this.heap.pop(); + this.siftDown(0); + return removedValue; + } + + heapify(array: T[]) { + if (array) { + this.heap = array; + } + + const maxIndex = Math.floor(this.size() / 2) - 1; + + for (let i = 0; i <= maxIndex; i++) { + this.siftDown(i); + } + + return this.heap; + } + + getAsArray() { + return this.heap; + } +} + +export class MaxHeap extends MinHeap { + constructor(protected compareFn: ICompareFunction = defaultCompare) { + super(compareFn); + this.compareFn = reverseCompare(compareFn); + } +} diff --git a/src/ts/data-structures/linked-list.ts b/src/ts/data-structures/linked-list.ts new file mode 100644 index 00000000..f0460c90 --- /dev/null +++ b/src/ts/data-structures/linked-list.ts @@ -0,0 +1,123 @@ +import { defaultEquals, IEqualsFunction } from '../util'; +import { Node } from './models/linked-list-models'; + +export default class LinkedList { + protected count = 0; + protected head: Node | undefined; + + constructor(protected equalsFn: IEqualsFunction = defaultEquals) {} + + push(element: T) { + const node = new Node(element); + let current; + + if (this.head == null) { + // catches null && undefined + this.head = node; + } else { + current = this.head; + + while (current.next != null) { + current = current.next; + } + + current.next = node; + } + this.count++; + } + + getElementAt(index: number) { + if (index >= 0 && index <= this.count) { + let node = this.head; + for (let i = 0; i < index && node != null; i++) { + node = node.next; + } + return node; + } + return undefined; + } + + insert(element: T, index: number) { + if (index >= 0 && index <= this.count) { + const node = new Node(element); + + if (index === 0) { + const current = this.head; + node.next = current; + this.head = node; + } else { + const previous = this.getElementAt(index - 1); + node.next = previous.next; + previous.next = node; + } + this.count++; + return true; + } + return false; + } + + removeAt(index: number) { + if (index >= 0 && index < this.count) { + let current = this.head; + + if (index === 0) { + this.head = current.next; + } else { + const previous = this.getElementAt(index - 1); + current = previous.next; + previous.next = current.next; + } + this.count--; + return current.element; + } + return undefined; + } + + remove(element: T) { + const index = this.indexOf(element); + return this.removeAt(index); + } + + indexOf(element: T) { + let current = this.head; + + for (let i = 0; i < this.size() && current != null; i++) { + if (this.equalsFn(element, current.element)) { + return i; + } + current = current.next; + } + + return -1; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return this.count; + } + + getHead() { + return this.head; + } + + clear() { + this.head = undefined; + this.count = 0; + } + + toString() { + if (this.head == null) { + return ''; + } + let objString = `${this.head.element}`; + let current = this.head.next; + for (let i = 1; i < this.size() && current != null; i++) { + objString = `${objString},${current.element}`; + current = current.next; + } + return objString; + } +} diff --git a/src/ts/data-structures/models/linked-list-models.ts b/src/ts/data-structures/models/linked-list-models.ts new file mode 100644 index 00000000..168d640e --- /dev/null +++ b/src/ts/data-structures/models/linked-list-models.ts @@ -0,0 +1,13 @@ +export class Node { + constructor(public element: T, public next?: Node) {} +} + +export class DoublyNode extends Node { + constructor( + public element: T, + public next?: DoublyNode, + public prev?: DoublyNode + ) { + super(element, next); + } +} diff --git a/src/ts/data-structures/models/node.ts b/src/ts/data-structures/models/node.ts new file mode 100644 index 00000000..f3e3f9aa --- /dev/null +++ b/src/ts/data-structures/models/node.ts @@ -0,0 +1,10 @@ +export class Node { + left: Node; + right: Node; + + constructor(public key: K) {} + + toString() { + return `${this.key}`; + } +} diff --git a/src/ts/data-structures/models/red-black-node.ts b/src/ts/data-structures/models/red-black-node.ts new file mode 100644 index 00000000..76493d9e --- /dev/null +++ b/src/ts/data-structures/models/red-black-node.ts @@ -0,0 +1,22 @@ +import { Node } from './node'; + +export enum Colors { + RED = 0, + BLACK = 1 +} + +export class RedBlackNode extends Node { + left: RedBlackNode; + right: RedBlackNode; + parent: RedBlackNode; + color: Colors; + + constructor(public key: K) { + super(key); + this.color = Colors.RED; + } + + isRed() { + return this.color === Colors.RED; + } +} diff --git a/src/ts/data-structures/models/value-pair-lazy.ts b/src/ts/data-structures/models/value-pair-lazy.ts new file mode 100644 index 00000000..57b6abbd --- /dev/null +++ b/src/ts/data-structures/models/value-pair-lazy.ts @@ -0,0 +1,7 @@ +import { ValuePair } from './value-pair'; + +export class ValuePairLazy extends ValuePair { + constructor(public key: K, public value: V, public isDeleted = false) { + super(key, value); + } +} diff --git a/src/ts/data-structures/models/value-pair.ts b/src/ts/data-structures/models/value-pair.ts new file mode 100644 index 00000000..eb4cff0a --- /dev/null +++ b/src/ts/data-structures/models/value-pair.ts @@ -0,0 +1,7 @@ +export class ValuePair { + constructor(public key: K, public value: V) {} + + toString() { + return `[#${this.key}: ${this.value}]`; + } +} diff --git a/src/ts/data-structures/priority-queue-array.ts b/src/ts/data-structures/priority-queue-array.ts new file mode 100644 index 00000000..6ad0d441 --- /dev/null +++ b/src/ts/data-structures/priority-queue-array.ts @@ -0,0 +1,58 @@ +import { Compare, defaultCompare, ICompareFunction } from '../util'; + +export default class PriorityQueue { + private items: T[]; + + constructor( + private compareFn: ICompareFunction = defaultCompare, + private compare: Compare = Compare.LESS_THAN + ) { + this.items = []; + } + + enqueue(element: T) { + let added = false; + + for (let i = 0; i < this.items.length; i++) { + if (this.compareFn(element, this.items[i]) === this.compare) { + this.items.splice(i, 0, element); + added = true; + break; + } + } + + if (!added) { + this.items.push(element); + } + } + + dequeue() { + return this.items.shift(); + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items[0]; + } + + isEmpty() { + return this.items.length === 0; + } + + clear() { + this.items = []; + } + + size() { + return this.items.length; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + return this.items; + } +} diff --git a/src/ts/data-structures/queue.ts b/src/ts/data-structures/queue.ts new file mode 100644 index 00000000..b6db45a5 --- /dev/null +++ b/src/ts/data-structures/queue.ts @@ -0,0 +1,58 @@ +export default class Queue { + private count: number; + private lowestCount: number; + private items: any; + + constructor() { + this.count = 0; + this.lowestCount = 0; + this.items = {}; + } + + enqueue(element: T) { + this.items[this.count] = element; + this.count++; + } + + dequeue() { + if (this.isEmpty()) { + return undefined; + } + const result = this.items[this.lowestCount]; + delete this.items[this.lowestCount]; + this.lowestCount++; + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.lowestCount]; + } + + isEmpty() { + return this.size() === 0; + } + + clear() { + this.items = {}; + this.count = 0; + this.lowestCount = 0; + } + + size() { + return this.count - this.lowestCount; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + let objString = `${this.items[this.lowestCount]}`; + for (let i = this.lowestCount + 1; i < this.count; i++) { + objString = `${objString},${this.items[i]}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/red-black-tree.ts b/src/ts/data-structures/red-black-tree.ts new file mode 100644 index 00000000..0d206e2f --- /dev/null +++ b/src/ts/data-structures/red-black-tree.ts @@ -0,0 +1,180 @@ +import { defaultCompare, ICompareFunction, Compare } from '../util'; +import BinarySearchTree from './binary-search-tree'; +import { RedBlackNode, Colors } from './models/red-black-node'; + +export default class RedBlackTree extends BinarySearchTree { + protected root: RedBlackNode; + + constructor(protected compareFn: ICompareFunction = defaultCompare) { + super(compareFn); + } + + /** + * Left left case: rotate right + * + * b a + * / \ / \ + * a e -> rotationLL(b) -> c b + * / \ / \ + * c d d e + * + * @param node Node + */ + private rotationLL(node: RedBlackNode) { + const tmp = node.left; + node.left = tmp.right; + if (tmp.right && tmp.right.key) { + tmp.right.parent = node; + } + tmp.parent = node.parent; + if (!node.parent) { + this.root = tmp; + } else { + if (node === node.parent.left) { + node.parent.left = tmp; + } else { + node.parent.right = tmp; + } + } + tmp.right = node; + node.parent = tmp; + } + + /** + * Right right case: rotate left + * + * a b + * / \ / \ + * c b -> rotationRR(a) -> a e + * / \ / \ + * d e c d + * + * @param node Node + */ + private rotationRR(node: RedBlackNode) { + const tmp = node.right; + node.right = tmp.left; + if (tmp.left && tmp.left.key) { + tmp.left.parent = node; + } + tmp.parent = node.parent; + if (!node.parent) { + this.root = tmp; + } else { + if (node === node.parent.left) { + node.parent.left = tmp; + } else { + node.parent.right = tmp; + } + } + tmp.left = node; + node.parent = tmp; + } + + insert(key: T) { + // special case: first key + if (this.root == null) { + this.root = new RedBlackNode(key); + this.root.color = Colors.BLACK; + } else { + const newNode = this.insertNode(this.root, key); + this.fixTreeProperties(newNode); + } + } + + protected insertNode(node: RedBlackNode, key: T): RedBlackNode { + if (this.compareFn(key, node.key) === Compare.LESS_THAN) { + if (node.left == null) { + node.left = new RedBlackNode(key); + node.left.parent = node; + return node.left; + } else { + return this.insertNode(node.left, key); + } + } else if (node.right == null) { + node.right = new RedBlackNode(key); + node.right.parent = node; + return node.right; + } else { + return this.insertNode(node.right, key); + } + } + + private fixTreeProperties(node: RedBlackNode) { + while (node && node.parent && node.parent.color === Colors.RED && node.color !== Colors.BLACK) { + let parent = node.parent; + const grandParent = parent.parent; + + // case A + if (grandParent && grandParent.left === parent) { + + const uncle = grandParent.right; + + // case 1: uncle of node is also red - only recoloring + if (uncle && uncle.isRed()) { + grandParent.color = Colors.RED; + parent.color = Colors.BLACK; + uncle.color = Colors.BLACK; + node = grandParent; + } else { + // case 2: node is right child - left rotate + if (node === parent.right) { + this.rotationRR(parent); + node = parent; + parent = node.parent; + } + + // case 3: node is left child - right rotate + this.rotationLL(grandParent); + // swap color + parent.color = Colors.BLACK; + grandParent.color = Colors.RED; + node = parent; + } + + } else { // case B: parent is right child of grand parent + + const uncle = grandParent.left; + + // case 1: uncle is read - only recoloring + if (uncle && uncle.isRed()) { + grandParent.color = Colors.RED; + parent.color = Colors.BLACK; + uncle.color = Colors.BLACK; + node = grandParent; + } else { + // case 2: node is left child - left rotate + if (node === parent.left) { + this.rotationLL(parent); + node = parent; + parent = node.parent; + } + + // case 3: node is right child - left rotate + this.rotationRR(grandParent); + // swap color + parent.color = Colors.BLACK; + grandParent.color = Colors.RED; + node = parent; + } + } + } + this.root.color = Colors.BLACK; + } + + getRoot() { + return this.root; + } + + /* private flipColors(node: RedBlackNode) { + node.left.flipColor(); + node.right.flipColor(); + } + + private isRed(node: RedBlackNode) { + if (!node) { + return false; + } + return node.isRed(); + }*/ +} diff --git a/src/ts/data-structures/set.ts b/src/ts/data-structures/set.ts new file mode 100644 index 00000000..c67faf75 --- /dev/null +++ b/src/ts/data-structures/set.ts @@ -0,0 +1,117 @@ +export default class Set { + private items: any; + + constructor() { + this.items = {}; + } + + add(element: T) { + if (!this.has(element)) { + this.items[element] = element; + return true; + } + return false; + } + + delete(element: T) { + if (this.has(element)) { + delete this.items[element]; + return true; + } + return false; + } + + has(element: T) { + // return this.items.hasOwnProperty(element); + return Object.prototype.hasOwnProperty.call(this.items, element); + } + + values(): T[] { + return Object.values(this.items); + } + + union(otherSet: Set) { + const unionSet = new Set(); + + this.values().forEach(value => unionSet.add(value)); + otherSet.values().forEach(value => unionSet.add(value)); + + return unionSet; + } + + intersection(otherSet: Set) { + const intersectionSet = new Set(); + + const values = this.values(); + const otherValues = otherSet.values(); + + let biggerSet = values; + let smallerSet = otherValues; + + if (otherValues.length - values.length > 0) { + biggerSet = otherValues; + smallerSet = values; + } + + smallerSet.forEach(value => { + if (biggerSet.includes(value)) { + intersectionSet.add(value); + } + }); + + return intersectionSet; + } + + difference(otherSet: Set) { + const differenceSet = new Set(); + + this.values().forEach(value => { + if (!otherSet.has(value)) { + differenceSet.add(value); + } + }); + + return differenceSet; + } + + isSubsetOf(otherSet: Set) { + if (this.size() > otherSet.size()) { + return false; + } + + let isSubset = true; + this.values().every(value => { + if (!otherSet.has(value)) { + isSubset = false; + return false; + } + return true; + }); + + return isSubset; + } + + isEmpty() { + return this.size() === 0; + } + + size() { + return Object.keys(this.items).length; + } + + clear() { + this.items = {}; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + const values = this.values(); + let objString = `${values[0]}`; + for (let i = 1; i < values.length; i++) { + objString = `${objString},${values[i].toString()}`; + } + return objString; + } +} diff --git a/src/ts/data-structures/sorted-linked-list.ts b/src/ts/data-structures/sorted-linked-list.ts new file mode 100644 index 00000000..f7832e81 --- /dev/null +++ b/src/ts/data-structures/sorted-linked-list.ts @@ -0,0 +1,43 @@ +import { Compare, defaultCompare, defaultEquals, ICompareFunction, IEqualsFunction } from '../util'; +import LinkedList from './linked-list'; + +export default class SortedLinkedList extends LinkedList { + constructor( + protected equalsFn: IEqualsFunction = defaultEquals, + protected compareFn: ICompareFunction = defaultCompare + ) { + super(equalsFn); + } + + push(element: T) { + if (this.isEmpty()) { + super.push(element); + } else { + const index = this.getIndexNextSortedElement(element); + super.insert(element, index); + } + } + + insert(element: T, index: number = 0) { + if (this.isEmpty()) { + return super.insert(element, 0); + } + index = this.getIndexNextSortedElement(element); + return super.insert(element, index); + } + + private getIndexNextSortedElement(element: T) { + let current = this.head; + let i = 0; + + for (; i < this.size() && current; i++) { + const comp = this.compareFn(element, current.element); + if (comp === Compare.LESS_THAN) { + return i; + } + current = current.next; + } + + return i; + } +} diff --git a/src/ts/data-structures/stack-array.ts b/src/ts/data-structures/stack-array.ts new file mode 100644 index 00000000..44bf91da --- /dev/null +++ b/src/ts/data-structures/stack-array.ts @@ -0,0 +1,39 @@ +export default class StackArray { + private items: T[]; + + constructor() { + this.items = []; + } + + push(element: T) { + this.items.push(element); + } + + pop() { + return this.items.pop(); + } + + peek() { + return this.items[this.items.length - 1]; + } + + isEmpty() { + return this.items.length === 0; + } + + size() { + return this.items.length; + } + + clear() { + this.items = []; + } + + toArray() { + return this.items; + } + + toString() { + return this.items.toString(); + } +} diff --git a/src/ts/data-structures/stack-linked-list.ts b/src/ts/data-structures/stack-linked-list.ts new file mode 100644 index 00000000..fa39023b --- /dev/null +++ b/src/ts/data-structures/stack-linked-list.ts @@ -0,0 +1,44 @@ +import DoublyLinkedList from './doubly-linked-list'; + +export default class StackLinkedList { + private items: DoublyLinkedList; + + constructor() { + this.items = new DoublyLinkedList(); + } + + push(element: T) { + this.items.push(element); + } + + pop() { + if (this.isEmpty()) { + return undefined; + } + const result = this.items.removeAt(this.size() - 1); + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items.getElementAt(this.size() - 1).element; + } + + isEmpty() { + return this.items.isEmpty(); + } + + size() { + return this.items.size(); + } + + clear() { + this.items.clear(); + } + + toString() { + return this.items.toString(); + } +} diff --git a/src/ts/data-structures/stack.ts b/src/ts/data-structures/stack.ts new file mode 100644 index 00000000..4ea30351 --- /dev/null +++ b/src/ts/data-structures/stack.ts @@ -0,0 +1,59 @@ +export default class Stack { + private count: number; + private items: any; + + constructor() { + this.count = 0; + this.items = {}; + } + + push(element: T) { + this.items[this.count] = element; + this.count++; + } + + pop() { + if (this.isEmpty()) { + return undefined; + } + this.count--; + const result = this.items[this.count]; + delete this.items[this.count]; + return result; + } + + peek() { + if (this.isEmpty()) { + return undefined; + } + return this.items[this.count - 1]; + } + + isEmpty() { + return this.count === 0; + } + + size() { + return this.count; + } + + clear() { + /* while (!this.isEmpty()) { + this.pop(); + } */ + + this.items = {}; + this.count = 0; + } + + toString() { + if (this.isEmpty()) { + return ''; + } + let objString = `${this.items[0]}`; + for (let i = 1; i < this.count; i++) { + objString = `${objString},${this.items[i]}`; + } + return objString; + } +} diff --git a/src/ts/index.ts b/src/ts/index.ts new file mode 100644 index 00000000..cc8aec85 --- /dev/null +++ b/src/ts/index.ts @@ -0,0 +1,116 @@ +import * as _util from './util'; +export const util = _util; + +export { default as Stack } from './data-structures/stack'; + +export { default as LinkedList } from './data-structures/linked-list'; +export { default as DoublyLinkedList } from './data-structures/doubly-linked-list'; +export { default as CircularLinkedList } from './data-structures/circular-linked-list'; +export { default as SortedLinkedList } from './data-structures/sorted-linked-list'; +export { default as StackLinkedList } from './data-structures/stack-linked-list'; +export { default as Set } from './data-structures/set'; +export { default as Dictionary } from './data-structures/dictionary'; +export { default as HashTable } from './data-structures/hash-table'; +export { default as HashTableSeparateChaining } from './data-structures/hash-table-separate-chaining'; +export { default as HashTableLinearProbing } from './data-structures/hash-table-linear-probing'; +export { default as HashTableLinearProbingLazy } from './data-structures/hash-table-linear-probing-lazy'; + +// chapter 08 +export { factorialIterative as factorialIterative } from './others/factorial'; +export { factorial as factorial} from './others/factorial'; +export { fibonacci as fibonacci} from './others/fibonacci'; +export { fibonacciIterative as fibonacciIterative} from './others/fibonacci'; +export { fibonacciMemoization as fibonacciMemoization} from './others/fibonacci'; + +// chapter 09 +export { default as BinarySearchTree } from './data-structures/binary-search-tree'; +export { default as AVLTree } from './data-structures/avl-tree'; +export { default as RedBlackTree } from './data-structures/red-black-tree'; + +// chapter 10 +export { MinHeap as MinHeap } from './data-structures/heap'; +export { MaxHeap as MaxHeap } from './data-structures/heap'; +export { default as heapSort } from './algorithms/sorting/heap-sort'; + +// chapter 11 +export { default as Graph } from './data-structures/graph'; +export { breadthFirstSearch as breadthFirstSearch } from './algorithms/graph/breadth-first-search'; +export { bfs as BFS } from './algorithms/graph/breadth-first-search'; +export { depthFirstSearch as depthFirstSearch } from './algorithms/graph/depth-first-search'; +export { DFS as DFS } from './algorithms/graph/depth-first-search'; +export { dijkstra as dijkstra } from './algorithms/graph/dijkstra'; +export { floydWarshall as floydWarshall } from './algorithms/graph/floyd-warshall'; +export { prim as prim } from './algorithms/graph/prim'; +export { kruskal as kruskal } from './algorithms/graph/kruskal'; + +// chapter 12 +export { shuffle as shuffle } from './algorithms/shuffle/fisher–yates'; + +export { bubbleSort as bubbleSort } from './algorithms/sorting/bubble-sort'; +export { modifiedBubbleSort as modifiedBubbleSort } from './algorithms/sorting/bubble-sort-improved'; +export { bucketSort as bucketSort } from './algorithms/sorting/bucket-sort'; +export { countingSort as countingSort } from './algorithms/sorting/counting-sort'; +export { insertionSort as insertionSort } from './algorithms/sorting/insertion-sort'; +export { mergeSort as mergeSort } from './algorithms/sorting/merge-sort'; +export { quickSort as quickSort } from './algorithms/sorting/quicksort'; +export { radixSort as radixSort } from './algorithms/sorting/radix-sort'; +export { selectionSort as selectionSort } from './algorithms/sorting/selection-sort'; +export { shellSort as shellSort } from './algorithms/sorting/shell-sort'; + +export { binarySearch as binarySearch } from './algorithms/search/binary-search'; +export { interpolationSearch as interpolationSearch } from './algorithms/search/interpolation-search'; +export { sequentialSearch as sequentialSearch } from './algorithms/search/sequential-search'; +export { findMaxValue as findMaxValue } from './algorithms/search/min-max-search'; +export { findMinValue as findMinValue } from './algorithms/search/min-max-search'; + +// chapter 14 +export { binarySearch as binarySearchRecursive } from './algorithms/search/binary-search-recursive'; +export { minCoinChange } from './algorithms/dynamic-programing/min-coin-change'; +export { minCoinChange as minCoinChangeGreedy } from './algorithms/greedy/min-coin-change'; +export { knapSack } from './algorithms/dynamic-programing/knapsack'; +export { knapSack as knapSackRecursive } from './algorithms/dynamic-programing/knapsack-recursive'; +export { knapSack as knapSackGreedy } from './algorithms/greedy/knapsack'; +export { lcs } from './algorithms/dynamic-programing/longest-common-subsequence'; +export { lcs as lcsPrint } from './algorithms/dynamic-programing/longest-common-subsequence-print'; +export { lcs as lcsRecursive } from './algorithms/greedy/longest-common-subsequence'; +export { matrixChainOrder } from './algorithms/dynamic-programing/matrix-chain-multiplication'; +export { matrixChainOrder as matrixChainOrderGreedy } from './algorithms/greedy/matrix-chain-multiplication'; +export { ratInAMaze } from './algorithms/backtracking/rat-in-maze'; +export { sudokuSolver } from './algorithms/backtracking/sudoku-solver'; + +// others +export { findDivisors } from './algorithms/math/find-divisors'; +export { gcd } from './algorithms/math/gcd'; +export { lcm } from './algorithms/math/lcm'; +export { greatestDifference } from './algorithms/math/greatest-difference'; +export { isPrime } from './algorithms/math/primality-test'; +export { testPrime } from './algorithms/math/primality-test'; +export { isPrime2 } from './algorithms/math/primality-test'; +export { sieveOfEratosthenes } from './algorithms/math/sieve-eratosthenes'; + + +/* import { hotPotato } from './others/hot-potato'; +import { palindromeChecker } from './others/palindrome-checker'; +import Deque from './data-structures/deque'; +import Queue from './data-structures/queue'; +import { hanoi, hanoiStack } from './others/hanoi'; +import { baseConverter, decimalToBinary } from './others/base-converter'; +import StackArray from './data-structures/stack-array'; +import Stack from './data-structures/stack'; +import { parenthesesChecker } from './others/balanced-symbols'; +import { MinHeap, MaxHeap } from './data-structures/heap'; + + +export { + Stack, + StackArray, + parenthesesChecker, + baseConverter, + decimalToBinary, + hanoi, + hanoiStack, + Queue, + Deque, + hotPotato, + palindromeChecker +}; */ diff --git a/src/ts/others/balanced-symbols.ts b/src/ts/others/balanced-symbols.ts new file mode 100644 index 00000000..f20b5830 --- /dev/null +++ b/src/ts/others/balanced-symbols.ts @@ -0,0 +1,29 @@ +import Stack from '../data-structures/stack'; + +export function parenthesesChecker(symbols: string) { + const stack = new Stack(); + const opens = '([{'; + const closers = ')]}'; + let balanced = true; + let index = 0; + let symbol: string; + let top: string; + + while (index < symbols.length && balanced) { + symbol = symbols[index]; + if (opens.indexOf(symbol) >= 0) { + stack.push(symbol); + } else { + if (stack.isEmpty()) { + balanced = false; + } else { + top = stack.pop(); + if (!(opens.indexOf(top) === closers.indexOf(symbol))) { + balanced = false; + } + } + } + index++; + } + return balanced && stack.isEmpty(); +} diff --git a/src/ts/others/base-converter.ts b/src/ts/others/base-converter.ts new file mode 100644 index 00000000..d65b27ef --- /dev/null +++ b/src/ts/others/base-converter.ts @@ -0,0 +1,42 @@ +import Stack from '../data-structures/stack'; + +export function decimalToBinary(decNumber: number) { + const remStack = new Stack(); + let rem: number; + let binaryString = ''; + + while (decNumber > 0) { + rem = Math.floor(decNumber % 2); + remStack.push(rem); + decNumber = Math.floor(decNumber / 2); + } + + while (!remStack.isEmpty()) { + binaryString += remStack.pop().toString(); + } + + return binaryString; +} + +export function baseConverter(decNumber: number, base: number) { + const remStack = new Stack(); + const digits = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + let rem: number; + let baseString = ''; + + if (!(base >= 2 && base <= 36)) { + return ''; + } + + while (decNumber > 0) { + rem = Math.floor(decNumber % base); + remStack.push(rem); + decNumber = Math.floor(decNumber / base); + } + + while (!remStack.isEmpty()) { + baseString += digits[remStack.pop()]; + } + + return baseString; +} diff --git a/src/ts/others/factorial.ts b/src/ts/others/factorial.ts new file mode 100644 index 00000000..e6e4cea9 --- /dev/null +++ b/src/ts/others/factorial.ts @@ -0,0 +1,20 @@ +export function factorialIterative(number: number) { + if (number < 0) { + return undefined; + } + let total = 1; + for (let n = number; n > 1; n--) { + total *= n; + } + return total; +} + +export function factorial(n: number): number { + if (n < 0) { + return undefined; + } + if (n === 1 || n === 0) { + return 1; + } + return n * factorial(n - 1); +} diff --git a/src/ts/others/fibonacci.ts b/src/ts/others/fibonacci.ts new file mode 100644 index 00000000..32d8db4f --- /dev/null +++ b/src/ts/others/fibonacci.ts @@ -0,0 +1,29 @@ +export function fibonacci(n: number): number { + if (n < 1) { return 0; } // {1} + if (n <= 2) { return 1; } // {2} + return fibonacci(n - 1) + fibonacci(n - 2); // {3} +} + +export function fibonacciIterative(n: number) { + if (n < 1) { return 0; } + let fibNMinus2 = 0; + let fibNMinus1 = 1; + let fibN = n; + for (let i = 2; i <= n; i++) { + // n >= 2 + fibN = fibNMinus1 + fibNMinus2; // f(n-1) + f(n-2) + fibNMinus2 = fibNMinus1; + fibNMinus1 = fibN; + } + return fibN; +} + +export function fibonacciMemoization(n: number) { + if (n < 1) { return 0; } + const memo = [0, 1]; + const fibonacciMem = (num: number): number => { + if (memo[num] != null) { return memo[num]; } + return (memo[num] = fibonacciMem(num - 1) + fibonacciMem(num - 2)); + }; + return fibonacciMem(n); +} diff --git a/src/ts/others/hanoi.ts b/src/ts/others/hanoi.ts new file mode 100644 index 00000000..fdc166a6 --- /dev/null +++ b/src/ts/others/hanoi.ts @@ -0,0 +1,64 @@ +import Stack from '../data-structures/stack'; + +function towerOfHanoi( + plates: number, + source: Stack, + helper: Stack, + dest: Stack, + sourceName: string, helperName: string, destName: string, + moves: any[] = [] +) { + if (plates <= 0) { + return moves; + } + if (plates === 1) { + dest.push(source.pop()); + const move: any = {}; + move[sourceName] = source.toString(); + move[helperName] = helper.toString(); + move[destName] = dest.toString(); + moves.push(move); + } else { + towerOfHanoi(plates - 1, source, dest, helper, sourceName, destName, helperName, moves); + dest.push(source.pop()); + const move: any = {}; + move[sourceName] = source.toString(); + move[helperName] = helper.toString(); + move[destName] = dest.toString(); + moves.push(move); + towerOfHanoi(plates - 1, helper, source, dest, helperName, sourceName, destName, moves); + } + return moves; +} + +export function hanoiStack(plates: number) { + const source = new Stack(); + const dest = new Stack(); + const helper = new Stack(); + + for (let i = plates; i > 0; i--) { + source.push(i); + } + + return towerOfHanoi(plates, source, helper, dest, 'source', 'helper', 'dest'); +} + +export function hanoi( + plates: number, + source: string, + helper: string, + dest: string, + moves: string[][] = [] +) { + if (plates <= 0) { + return moves; + } + if (plates === 1) { + moves.push([source, dest]); + } else { + hanoi(plates - 1, source, dest, helper, moves); + moves.push([source, dest]); + hanoi(plates - 1, helper, source, dest, moves); + } + return moves; +} diff --git a/src/ts/others/hot-potato.ts b/src/ts/others/hot-potato.ts new file mode 100644 index 00000000..f6eb8349 --- /dev/null +++ b/src/ts/others/hot-potato.ts @@ -0,0 +1,22 @@ +import Queue from '../data-structures/queue'; + +export function hotPotato(elementsList: any[], num: number) { + const queue = new Queue(); + const elimitatedList = []; + + for (let i = 0; i < elementsList.length; i++) { + queue.enqueue(elementsList[i]); + } + + while (queue.size() > 1) { + for (let i = 0; i < num; i++) { + queue.enqueue(queue.dequeue()); + } + elimitatedList.push(queue.dequeue()); + } + + return { + elimitated: elimitatedList, + winner: queue.dequeue() + }; +} diff --git a/src/ts/others/palindrome-checker.ts b/src/ts/others/palindrome-checker.ts new file mode 100644 index 00000000..4742d1cd --- /dev/null +++ b/src/ts/others/palindrome-checker.ts @@ -0,0 +1,27 @@ +import Deque from '../data-structures/deque'; + +export function palindromeChecker(aString: string) { + + if (aString === undefined || aString === null || + (aString !== null && aString.length === 0)) { + return false; + } + + const deque = new Deque(); + const lowerString = aString.toLocaleLowerCase().split(' ').join(''); + let firstChar: string, lastChar: string; + + for (let i = 0; i < lowerString.length; i++) { + deque.addBack(lowerString.charAt(i)); + } + + while (deque.size() > 1) { + firstChar = deque.removeFront(); + lastChar = deque.removeBack(); + if (firstChar !== lastChar) { + return false; + } + } + + return true; +} diff --git a/src/ts/util.ts b/src/ts/util.ts new file mode 100644 index 00000000..8c9f75f0 --- /dev/null +++ b/src/ts/util.ts @@ -0,0 +1,60 @@ +export type ICompareFunction = (a: T, b: T) => number; + +export type IEqualsFunction = (a: T, b: T) => boolean; + +export type IDiffFunction = (a: T, b: T) => number; + +export const DOES_NOT_EXIST = -1; + +export enum Compare { + LESS_THAN = -1, + BIGGER_THAN = 1, + EQUALS = 0 +} + +export function lesserEquals(a: T, b: T, compareFn: ICompareFunction) { + const comp = compareFn(a, b); + return comp === Compare.LESS_THAN || comp === Compare.EQUALS; +} + +export function biggerEquals(a: T, b: T, compareFn: ICompareFunction) { + const comp = compareFn(a, b); + return comp === Compare.BIGGER_THAN || comp === Compare.EQUALS; +} + +export function defaultCompare(a: T, b: T): number { + if (a === b) { + return Compare.EQUALS; + } + return a < b ? Compare.LESS_THAN : Compare.BIGGER_THAN; +} + +export function defaultEquals(a: T, b: T): boolean { + return a === b; +} + +export function defaultToString(item: any): string { + if (item === null) { + return 'NULL'; + } else if (item === undefined) { + return 'UNDEFINED'; + } else if (typeof item === 'string' || item instanceof String) { + return `${item}`; + } + return item.toString(); +} + +export function swap(array: any[], a: number, b: number) { + /* const temp = array[a]; + array[a] = array[b]; + array[b] = temp; */ + [array[a], array[b]] = [array[b], array[a]]; +} + +export function reverseCompare(compareFn: ICompareFunction): ICompareFunction { + return (a, b) => compareFn(b, a); +} + +export function defaultDiff(a: T, b: T): number { + return Number(a) - Number(b); +} diff --git a/test/js/algorithms/backtracking/rat-in-maze.spec.js b/test/js/algorithms/backtracking/rat-in-maze.spec.js new file mode 100644 index 00000000..b88e1d60 --- /dev/null +++ b/test/js/algorithms/backtracking/rat-in-maze.spec.js @@ -0,0 +1,21 @@ +import 'mocha'; +import { expect } from 'chai'; +import { ratInAMaze } from '../../../../src/js/index'; + +describe('Rat in a maze', () => { + it('rat in a maze solver', () => { + const maze = [ + [1, 0, 0, 0], + [1, 1, 1, 1], + [0, 0, 1, 0], + [0, 1, 1, 1] + ]; + const solution = [ + [1, 0, 0, 0], + [1, 1, 1, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ]; + expect(ratInAMaze(maze)).to.deep.equal(solution); + }); +}); diff --git a/test/js/algorithms/backtracking/sudoku-solver.spec.js b/test/js/algorithms/backtracking/sudoku-solver.spec.js new file mode 100644 index 00000000..f4d8c216 --- /dev/null +++ b/test/js/algorithms/backtracking/sudoku-solver.spec.js @@ -0,0 +1,57 @@ +import 'mocha'; +import { expect } from 'chai'; +import { sudokuSolver } from '../../../../src/js/index'; + +describe('Sudoku Solver', () => { + it('sudoku solver', () => { + const grid = [ + [3, 0, 6, 5, 0, 8, 4, 0, 0], + [5, 2, 0, 0, 0, 0, 0, 0, 0], + [0, 8, 7, 0, 0, 0, 0, 3, 1], + [0, 0, 3, 0, 1, 0, 0, 8, 0], + [9, 0, 0, 8, 6, 3, 0, 0, 5], + [0, 5, 0, 0, 9, 0, 6, 0, 0], + [1, 3, 0, 0, 0, 0, 2, 5, 0], + [0, 0, 0, 0, 0, 0, 0, 7, 4], + [0, 0, 5, 2, 0, 6, 3, 0, 0] + ]; + const solution = [ + [3, 1, 6, 5, 7, 8, 4, 9, 2], + [5, 2, 9, 1, 3, 4, 7, 6, 8], + [4, 8, 7, 6, 2, 9, 5, 3, 1], + [2, 6, 3, 4, 1, 5, 9, 8, 7], + [9, 7, 4, 8, 6, 3, 1, 2, 5], + [8, 5, 1, 7, 9, 2, 6, 4, 3], + [1, 3, 8, 9, 4, 7, 2, 5, 6], + [6, 9, 2, 3, 5, 1, 8, 7, 4], + [7, 4, 5, 2, 8, 6, 3, 1, 9] + ]; + expect(sudokuSolver(grid)).to.deep.equal(solution); + }); + + it('sudoku solver 2', () => { + const grid = [ + [5, 3, 0, 0, 7, 0, 0, 0, 0], + [6, 0, 0, 1, 9, 5, 0, 0, 0], + [0, 9, 8, 0, 0, 0, 0, 6, 0], + [8, 0, 0, 0, 6, 0, 0, 0, 3], + [4, 0, 0, 8, 0, 3, 0, 0, 1], + [7, 0, 0, 0, 2, 0, 0, 0, 6], + [0, 6, 0, 0, 0, 0, 2, 8, 0], + [0, 0, 0, 4, 1, 9, 0, 0, 5], + [0, 0, 0, 0, 8, 0, 0, 7, 9] + ]; + const solution = [ + [5, 3, 4, 6, 7, 8, 9, 1, 2], + [6, 7, 2, 1, 9, 5, 3, 4, 8], + [1, 9, 8, 3, 4, 2, 5, 6, 7], + [8, 5, 9, 7, 6, 1, 4, 2, 3], + [4, 2, 6, 8, 5, 3, 7, 9, 1], + [7, 1, 3, 9, 2, 4, 8, 5, 6], + [9, 6, 1, 5, 3, 7, 2, 8, 4], + [2, 8, 7, 4, 1, 9, 6, 3, 5], + [3, 4, 5, 2, 8, 6, 1, 7, 9] + ]; + expect(sudokuSolver(grid)).to.deep.equal(solution); + }); +}); diff --git a/test/js/algorithms/dynamic-programming/knapsack-recursive.spec.js b/test/js/algorithms/dynamic-programming/knapsack-recursive.spec.js new file mode 100644 index 00000000..589b8e9d --- /dev/null +++ b/test/js/algorithms/dynamic-programming/knapsack-recursive.spec.js @@ -0,0 +1,15 @@ +import 'mocha'; +import { expect } from 'chai'; +import { knapSackRecursive } from '../../../../src/js/index'; + +describe('KnapSack Dynamic Programming - Recursive', () => { + + it('works with recursive approach', () => { + const values = [3, 4, 5]; + const weights = [2, 3, 4]; + const capacity = 5; + const n = values.length; + + expect(knapSackRecursive(capacity, weights, values, n)).to.equal(7); + }); +}); diff --git a/test/js/algorithms/dynamic-programming/knapsack.spec.js b/test/js/algorithms/dynamic-programming/knapsack.spec.js new file mode 100644 index 00000000..47e2ab37 --- /dev/null +++ b/test/js/algorithms/dynamic-programming/knapsack.spec.js @@ -0,0 +1,15 @@ +import 'mocha'; +import { expect } from 'chai'; +import { knapSack } from '../../../../src/js/index'; + +describe('KnapSack Dynamic Programming', () => { + + it('works with DP approach', () => { + const values = [3, 4, 5]; + const weights = [2, 3, 4]; + const capacity = 5; + const n = values.length; + + expect(knapSack(capacity, weights, values, n)).to.equal(7); + }); +}); diff --git a/test/js/algorithms/dynamic-programming/longest-common-subsequence-print.spec.js b/test/js/algorithms/dynamic-programming/longest-common-subsequence-print.spec.js new file mode 100644 index 00000000..8b5ba9fe --- /dev/null +++ b/test/js/algorithms/dynamic-programming/longest-common-subsequence-print.spec.js @@ -0,0 +1,13 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcsPrint } from '../../../../src/js/index'; + +describe('LCS Dynamic Programming with print solution', () => { + + it('works with DP approach with print solution', () => { + const wordX = 'acbaed'; + const wordY = 'abcadf'; + + expect(lcsPrint(wordX, wordY)).to.equal('acad'); + }); +}); diff --git a/test/js/algorithms/dynamic-programming/longest-common-subsequence.spec.js b/test/js/algorithms/dynamic-programming/longest-common-subsequence.spec.js new file mode 100644 index 00000000..121cf4fa --- /dev/null +++ b/test/js/algorithms/dynamic-programming/longest-common-subsequence.spec.js @@ -0,0 +1,13 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcs } from '../../../../src/js/index'; + +describe('LCS Dynamic Programming', () => { + + it('works with DP approach', () => { + const wordX = 'acbaed'; + const wordY = 'abcadf'; + + expect(lcs(wordX, wordY)).to.equal(4); + }); +}); diff --git a/test/js/algorithms/dynamic-programming/matrix-chain-multiplication.spec.js b/test/js/algorithms/dynamic-programming/matrix-chain-multiplication.spec.js new file mode 100644 index 00000000..db1972e3 --- /dev/null +++ b/test/js/algorithms/dynamic-programming/matrix-chain-multiplication.spec.js @@ -0,0 +1,12 @@ +import 'mocha'; +import { expect } from 'chai'; +import { matrixChainOrder } from '../../../../src/js/index'; + +describe('Matrix Chain Multiplication', () => { + + it('works with DP approach', () => { + const p = [10, 100, 5, 50, 1]; + + expect(matrixChainOrder(p)).to.equal(1750); + }); +}); diff --git a/test/js/algorithms/dynamic-programming/min-coin-change.spec.js b/test/js/algorithms/dynamic-programming/min-coin-change.spec.js new file mode 100644 index 00000000..ecc8be1b --- /dev/null +++ b/test/js/algorithms/dynamic-programming/min-coin-change.spec.js @@ -0,0 +1,30 @@ +import 'mocha'; +import { expect } from 'chai'; +import { minCoinChange } from '../../../../src/js/index'; + +describe('Dynamic Programming: Min Coin Change', () => { + + it('works with amount 0', () => { + expect(minCoinChange([1, 2, 3], 0)).to.deep.equal([]); + }); + + it('works with amount 1', () => { + expect(minCoinChange([1, 2, 3], 1)).to.deep.equal([1]); + }); + + it('works with amount 2', () => { + expect(minCoinChange([1, 2, 3], 2)).to.deep.equal([2]); + }); + + it('works with amount 3', () => { + expect(minCoinChange([1, 2, 3], 3)).to.deep.equal([3]); + }); + + it('works with amount 4', () => { + expect(minCoinChange([1, 2, 3], 4)).to.deep.equal([1, 3]); + }); + + it('works with amount 6', () => { + expect(minCoinChange([1, 2, 3], 6)).to.deep.equal([3, 3]); + }); +}); diff --git a/test/js/algorithms/graph/breadth-first-search.spec.js b/test/js/algorithms/graph/breadth-first-search.spec.js new file mode 100644 index 00000000..1d7b5e75 --- /dev/null +++ b/test/js/algorithms/graph/breadth-first-search.spec.js @@ -0,0 +1,65 @@ +import 'mocha'; +import { expect } from 'chai'; +import { BFS, breadthFirstSearch, Graph } from '../../../../src/js/index'; + +describe('Breadth First Search', () => { + let count; + const vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + let graph; + + function assertCallback(value) { + expect(value).to.equal(vertices[count]); + count++; + } + + beforeEach(() => { + count = 0; + graph = new Graph(); + + for (let i = 0; i < vertices.length; i++) { + graph.addVertex(vertices[i]); + } + + graph.addEdge('A', 'B'); + graph.addEdge('A', 'C'); + graph.addEdge('A', 'D'); + graph.addEdge('C', 'D'); + graph.addEdge('C', 'G'); + graph.addEdge('D', 'G'); + graph.addEdge('D', 'H'); + graph.addEdge('B', 'E'); + graph.addEdge('B', 'F'); + graph.addEdge('E', 'I'); + }); + + it('breadthFirstSearch', () => { + breadthFirstSearch(graph, vertices[0], assertCallback); + }); + + it('sorthest path - BFS', () => { + const shortestPathA = BFS(graph, vertices[0]); + + expect(shortestPathA.distances).to.deep.equal({ + A: 0, + B: 1, + C: 1, + D: 1, + E: 2, + F: 2, + G: 2, + H: 2, + I: 3 + }); + expect(shortestPathA.predecessors).to.deep.equal({ + A: null, + B: 'A', + C: 'A', + D: 'A', + E: 'B', + F: 'B', + G: 'C', + H: 'D', + I: 'E' + }); + }); +}); diff --git a/test/js/algorithms/graph/depth-first-search.spec.js b/test/js/algorithms/graph/depth-first-search.spec.js new file mode 100644 index 00000000..e0cbcde9 --- /dev/null +++ b/test/js/algorithms/graph/depth-first-search.spec.js @@ -0,0 +1,64 @@ +import 'mocha'; +import { expect } from 'chai'; +import { DFS, depthFirstSearch, Graph } from '../../../../src/js/index'; + +describe('Depth First Search', () => { + let count; + const vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + const dfsCallBack = ['A', 'B', 'E', 'I', 'F', 'C', 'D', 'G', 'H']; + let graph; + + beforeEach(() => { + count = 0; + graph = new Graph(true); + }); + + function assertCallback(value) { + expect(value).to.equal(dfsCallBack[count]); + count++; + } + + it('depthFirstSearch', () => { + for (let i = 0; i < vertices.length; i++) { + graph.addVertex(vertices[i]); + } + + graph.addEdge('A', 'B'); + graph.addEdge('A', 'C'); + graph.addEdge('A', 'D'); + graph.addEdge('C', 'D'); + graph.addEdge('C', 'G'); + graph.addEdge('D', 'G'); + graph.addEdge('D', 'H'); + graph.addEdge('B', 'E'); + graph.addEdge('B', 'F'); + graph.addEdge('E', 'I'); + + depthFirstSearch(graph, assertCallback); + }); + + it('topological sort - DFS', () => { + const myVertices = ['A', 'B', 'C', 'D', 'E', 'F']; + for (let i = 0; i < myVertices.length; i++) { + graph.addVertex(myVertices[i]); + } + graph.addEdge('A', 'C'); + graph.addEdge('A', 'D'); + graph.addEdge('B', 'D'); + graph.addEdge('B', 'E'); + graph.addEdge('C', 'F'); + graph.addEdge('F', 'E'); + + const result = DFS(graph); + + expect(result.discovery).to.deep.equal({ + A: 1, B: 11, C: 2, D: 8, E: 4, F: 3 + }); + expect(result.finished).to.deep.equal({ + A: 10, B: 12, C: 7, D: 9, E: 5, F: 6 + }); + expect(result.predecessors).to.deep.equal({ + A: null, B: null, C: 'A', D: 'A', E: 'F', F: 'C' + }); + }); +}); diff --git a/test/js/algorithms/graph/dijkstra.spec.js b/test/js/algorithms/graph/dijkstra.spec.js new file mode 100644 index 00000000..7a88f040 --- /dev/null +++ b/test/js/algorithms/graph/dijkstra.spec.js @@ -0,0 +1,21 @@ +import 'mocha'; +import { expect } from 'chai'; +import { dijkstra } from '../../../../src/js/index'; + +describe('Dijkstra\'s Algorithm - Shortest Path', () => { + + it('Shortest Path', () => { + const graph = [ + [0, 2, 4, 0, 0, 0], + [0, 0, 2, 4, 2, 0], + [0, 0, 0, 0, 3, 0], + [0, 0, 0, 0, 0, 2], + [0, 0, 0, 3, 0, 2], + [0, 0, 0, 0, 0, 0] + ]; + + expect(dijkstra(graph, 0)).to.deep.equal([0, 2, 4, 6, 4, 6]); + + }); + +}); diff --git a/test/js/algorithms/graph/floyd-warshall.spec.js b/test/js/algorithms/graph/floyd-warshall.spec.js new file mode 100644 index 00000000..0f62cb7a --- /dev/null +++ b/test/js/algorithms/graph/floyd-warshall.spec.js @@ -0,0 +1,26 @@ +import 'mocha'; +import { expect } from 'chai'; +import { floydWarshall } from '../../../../src/js/index'; + +describe('Floyd-Warshall Algorithm - All-Pairs Shortest Path', () => { + it('All-Pairs Shortest Path', () => { + const INF = Infinity; + const graph = [ + [INF, 2, 4, INF, INF, INF], + [INF, INF, 2, 4, 2, INF], + [INF, INF, INF, INF, 3, INF], + [INF, INF, INF, INF, INF, 2], + [INF, INF, INF, 3, INF, 2], + [INF, INF, INF, INF, INF, INF] + ]; + + expect(floydWarshall(graph)).to.deep.equal([ + [0, 2, 4, 6, 4, 6], + [INF, 0, 2, 4, 2, 4], + [INF, INF, 0, 6, 3, 5], + [INF, INF, INF, 0, INF, 2], + [INF, INF, INF, 3, 0, 2], + [INF, INF, INF, INF, INF, 0] + ]); + }); +}); diff --git a/test/js/algorithms/graph/kruskal.spec.js b/test/js/algorithms/graph/kruskal.spec.js new file mode 100644 index 00000000..38a2132c --- /dev/null +++ b/test/js/algorithms/graph/kruskal.spec.js @@ -0,0 +1,18 @@ +import 'mocha'; +import { expect } from 'chai'; +import { kruskal } from '../../../../src/js/index'; + +describe('Kruskal Algorithm - Minimum Spanning Tree', () => { + it('Minimum Spanning Tree', () => { + const graph = [ + [0, 2, 4, 0, 0, 0], + [2, 0, 2, 4, 2, 0], + [4, 2, 0, 0, 3, 0], + [0, 4, 0, 0, 3, 2], + [0, 2, 3, 3, 0, 2], + [0, 0, 0, 2, 2, 0] + ]; + + expect(kruskal(graph)).to.deep.equal([ , 0, 1, 1, 1, 3]); + }); +}); diff --git a/test/js/algorithms/graph/prim.spec.js b/test/js/algorithms/graph/prim.spec.js new file mode 100644 index 00000000..9e0b6b31 --- /dev/null +++ b/test/js/algorithms/graph/prim.spec.js @@ -0,0 +1,18 @@ +import 'mocha'; +import { expect } from 'chai'; +import { prim } from '../../../../src/js/index'; + +describe('Prim\'s Algorithm - Minimum Spanning Tree', () => { + it('Minimum Spanning Tree', () => { + const graph = [ + [0, 2, 4, 0, 0, 0], + [2, 0, 2, 4, 2, 0], + [4, 2, 0, 0, 3, 0], + [0, 4, 0, 0, 3, 2], + [0, 2, 3, 3, 0, 2], + [0, 0, 0, 2, 2, 0] + ]; + + expect(prim(graph)).to.deep.equal([-1, 0, 1, 5, 1, 4]); + }); +}); diff --git a/test/js/algorithms/greedy/knapsack.spec.js b/test/js/algorithms/greedy/knapsack.spec.js new file mode 100644 index 00000000..39be668a --- /dev/null +++ b/test/js/algorithms/greedy/knapsack.spec.js @@ -0,0 +1,14 @@ +import 'mocha'; +import { expect } from 'chai'; +import { knapSackGreedy } from '../../../../src/js/index'; + +describe('KnapSack Greedy', () => { + + it('works with greedy approach', () => { + const values = [3, 4, 5]; + const weights = [2, 3, 4]; + const capacity = 5; + + expect(knapSackGreedy(capacity, weights, values)).to.equal(7); + }); +}); diff --git a/test/js/algorithms/greedy/longest-common-subsequence.spec.js b/test/js/algorithms/greedy/longest-common-subsequence.spec.js new file mode 100644 index 00000000..7be0e4c4 --- /dev/null +++ b/test/js/algorithms/greedy/longest-common-subsequence.spec.js @@ -0,0 +1,13 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcsRecursive } from '../../../../src/js/index'; + +describe('LCS Greedy', () => { + + it('works with Greedy approach', () => { + const wordX = 'acbaed'; + const wordY = 'abcadf'; + + expect(lcsRecursive(wordX, wordY)).to.equal(4); + }); +}); diff --git a/test/js/algorithms/greedy/matrix-chain-multiplication.spec.js b/test/js/algorithms/greedy/matrix-chain-multiplication.spec.js new file mode 100644 index 00000000..c9d53888 --- /dev/null +++ b/test/js/algorithms/greedy/matrix-chain-multiplication.spec.js @@ -0,0 +1,12 @@ +import 'mocha'; +import { expect } from 'chai'; +import { matrixChainOrderGreedy } from '../../../../src/js/index'; + +describe('Matrix Chain Multiplication', () => { + + it('works with DP approach', () => { + const p = [10, 100, 5, 50, 1]; + + expect(matrixChainOrderGreedy(p)).to.equal(1750); + }); +}); diff --git a/test/js/algorithms/greedy/min-coin-change.spec.js b/test/js/algorithms/greedy/min-coin-change.spec.js new file mode 100644 index 00000000..ffa0b674 --- /dev/null +++ b/test/js/algorithms/greedy/min-coin-change.spec.js @@ -0,0 +1,12 @@ +import 'mocha'; +import { expect } from 'chai'; +import { minCoinChangeGreedy } from '../../../../src/js/index'; + +describe('Min Coin Change Greedy', () => { + + it('works with greedy approach', () => { + expect(minCoinChangeGreedy([1, 5, 10], 15)).to.deep.equal([10, 5]); + expect(minCoinChangeGreedy([1, 3, 4], 6)).to.deep.equal([4, 1, 1]); + }); + +}); diff --git a/test/js/algorithms/search/binary-search-recursive.spec.js b/test/js/algorithms/search/binary-search-recursive.spec.js new file mode 100644 index 00000000..8aab4959 --- /dev/null +++ b/test/js/algorithms/search/binary-search-recursive.spec.js @@ -0,0 +1,4 @@ +import { binarySearchRecursive } from '../../../../src/js/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(binarySearchRecursive, 'Binary Search Recursive'); diff --git a/test/js/algorithms/search/binary-search.spec.js b/test/js/algorithms/search/binary-search.spec.js new file mode 100644 index 00000000..220c1b28 --- /dev/null +++ b/test/js/algorithms/search/binary-search.spec.js @@ -0,0 +1,4 @@ +import { binarySearch } from '../../../../src/js/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(binarySearch, 'Binary Search'); diff --git a/test/js/algorithms/search/interpolation-search.spec.js b/test/js/algorithms/search/interpolation-search.spec.js new file mode 100644 index 00000000..1daff1cc --- /dev/null +++ b/test/js/algorithms/search/interpolation-search.spec.js @@ -0,0 +1,4 @@ +import { interpolationSearch } from '../../../../src/js/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(interpolationSearch, 'Interpolation Search', { customEquals: false }); diff --git a/test/js/algorithms/search/min-max-search.spec.js b/test/js/algorithms/search/min-max-search.spec.js new file mode 100644 index 00000000..0c789a2f --- /dev/null +++ b/test/js/algorithms/search/min-max-search.spec.js @@ -0,0 +1,31 @@ +import 'mocha'; +import { expect } from 'chai'; +import { findMinValue, findMaxValue } from '../../../../src/js/index'; + +describe('Min and Max Values Search', () => { + const SIZE = 10; + + function createSortedArray() { + const array = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('min value - works with empty arrays', () => { + expect(findMinValue([])).to.equal(undefined); + }); + + it('max value - works with empty arrays', () => { + expect(findMaxValue([])).to.equal(undefined); + }); + + it('min value', () => { + expect(findMinValue(createSortedArray())).to.equal(1); + }); + + it('max value', () => { + expect(findMaxValue(createSortedArray())).to.equal(SIZE); + }); +}); diff --git a/test/js/algorithms/search/search-algorithms-tests.js b/test/js/algorithms/search/search-algorithms-tests.js new file mode 100644 index 00000000..f0c698a2 --- /dev/null +++ b/test/js/algorithms/search/search-algorithms-tests.js @@ -0,0 +1,51 @@ +import 'mocha'; +import { expect } from 'chai'; + +const customEquals = (a, b) => a.key === b.key; + +export function testSearchAlgorithm( + searchAlgorithm, + algorithmName, + config = { customEquals: true } +) { + describe(algorithmName, () => { + const SIZE = 10; + + function createSortedArray() { + const array = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('works with empty arrays', () => { + expect(searchAlgorithm([], 1)).to.equal(-1); + }); + + it('finds value at the first position', () => { + const array = createSortedArray(); + expect(searchAlgorithm(array, 1)).to.equal(0); + }); + + it('finds value at the last position', () => { + const array = createSortedArray(); + expect(searchAlgorithm(array, SIZE)).to.equal(SIZE - 1); + }); + + it('finds value at different positions', () => { + const array = createSortedArray(); + + for (let value = 1; value <= SIZE; value++) { + expect(searchAlgorithm(array, value)).to.equal(value - 1); + } + }); + + if (config.customEquals) { + it('finds value with custom equals function', () => { + const array = [{ key: 1 }, { key: 2 }, { key: 3 }]; + expect(searchAlgorithm(array, { key: 2 }, customEquals)).to.equal(1); + }); + } + }); +} diff --git a/test/js/algorithms/search/sequential-search.spec.js b/test/js/algorithms/search/sequential-search.spec.js new file mode 100644 index 00000000..a308474e --- /dev/null +++ b/test/js/algorithms/search/sequential-search.spec.js @@ -0,0 +1,4 @@ +import { sequentialSearch } from '../../../../src/js/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(sequentialSearch, 'Sequential Search'); diff --git "a/test/js/algorithms/shuffle/fisher\342\200\223yates.spec.js" "b/test/js/algorithms/shuffle/fisher\342\200\223yates.spec.js" new file mode 100644 index 00000000..6e87916c --- /dev/null +++ "b/test/js/algorithms/shuffle/fisher\342\200\223yates.spec.js" @@ -0,0 +1,31 @@ +import 'mocha'; +import { expect } from 'chai'; +import { shuffle } from '../../../../src/js/index'; + +describe('Fisher-Yates Suffle', () => { + const SIZE = 100; + + function createSortedArray() { + const array = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('works with empty arrays', () => { + expect(shuffle([])).to.deep.equal([]); + }); + + it('works with arrays with a single value', () => { + const array = [1]; + expect(shuffle(array)).to.deep.equal(array); + }); + + it('works with sorted arrays', () => { + let array = createSortedArray(); + const sortedArray = createSortedArray(); + array = shuffle(array); + expect(array).to.not.deep.equal(sortedArray); + }); +}); diff --git a/test/js/algorithms/sorting/bubble-sort-improved.spec.js b/test/js/algorithms/sorting/bubble-sort-improved.spec.js new file mode 100644 index 00000000..1ad03b39 --- /dev/null +++ b/test/js/algorithms/sorting/bubble-sort-improved.spec.js @@ -0,0 +1,4 @@ +import { modifiedBubbleSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(modifiedBubbleSort, 'Bubble Sort - Improved'); diff --git a/test/js/algorithms/sorting/bubble-sort.spec.js b/test/js/algorithms/sorting/bubble-sort.spec.js new file mode 100644 index 00000000..b903df74 --- /dev/null +++ b/test/js/algorithms/sorting/bubble-sort.spec.js @@ -0,0 +1,4 @@ +import { bubbleSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(bubbleSort, 'Bubble Sort'); diff --git a/test/js/algorithms/sorting/bucket-sort.spec.js b/test/js/algorithms/sorting/bucket-sort.spec.js new file mode 100644 index 00000000..2a00d8db --- /dev/null +++ b/test/js/algorithms/sorting/bucket-sort.spec.js @@ -0,0 +1,4 @@ +import { bucketSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(bucketSort, 'Bucket Sort', { reverseCompare: false }); diff --git a/test/js/algorithms/sorting/counting-sort.spec.js b/test/js/algorithms/sorting/counting-sort.spec.js new file mode 100644 index 00000000..783a48a5 --- /dev/null +++ b/test/js/algorithms/sorting/counting-sort.spec.js @@ -0,0 +1,4 @@ +import { countingSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(countingSort, 'Counting Sort', { reverseCompare: false }); diff --git a/test/js/algorithms/sorting/heap-sort.spec.js b/test/js/algorithms/sorting/heap-sort.spec.js new file mode 100644 index 00000000..ae3816dc --- /dev/null +++ b/test/js/algorithms/sorting/heap-sort.spec.js @@ -0,0 +1,4 @@ +import { heapSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(heapSort, 'Heap Sort'); diff --git a/test/js/algorithms/sorting/insertion-sort.spec.js b/test/js/algorithms/sorting/insertion-sort.spec.js new file mode 100644 index 00000000..c28a69de --- /dev/null +++ b/test/js/algorithms/sorting/insertion-sort.spec.js @@ -0,0 +1,4 @@ +import { insertionSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(insertionSort, 'Insertion Sort'); diff --git a/test/js/algorithms/sorting/merge-sort.spec.js b/test/js/algorithms/sorting/merge-sort.spec.js new file mode 100644 index 00000000..5b161785 --- /dev/null +++ b/test/js/algorithms/sorting/merge-sort.spec.js @@ -0,0 +1,4 @@ +import { mergeSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(mergeSort, 'Merge Sort'); diff --git a/test/js/algorithms/sorting/quicksort.spec.js b/test/js/algorithms/sorting/quicksort.spec.js new file mode 100644 index 00000000..0cbe027a --- /dev/null +++ b/test/js/algorithms/sorting/quicksort.spec.js @@ -0,0 +1,4 @@ +import { quickSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(quickSort, 'Quick Sort'); diff --git a/test/js/algorithms/sorting/radix-sort.spec.js b/test/js/algorithms/sorting/radix-sort.spec.js new file mode 100644 index 00000000..af6a5b07 --- /dev/null +++ b/test/js/algorithms/sorting/radix-sort.spec.js @@ -0,0 +1,4 @@ +import { radixSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(radixSort, 'Radix Sort', { reverseCompare: false }); diff --git a/test/js/algorithms/sorting/selection-sort.spec.js b/test/js/algorithms/sorting/selection-sort.spec.js new file mode 100644 index 00000000..3d6cd3cc --- /dev/null +++ b/test/js/algorithms/sorting/selection-sort.spec.js @@ -0,0 +1,4 @@ +import { selectionSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(selectionSort, 'Selection Sort'); diff --git a/test/js/algorithms/sorting/shell-sort.spec.js b/test/js/algorithms/sorting/shell-sort.spec.js new file mode 100644 index 00000000..92aa33a5 --- /dev/null +++ b/test/js/algorithms/sorting/shell-sort.spec.js @@ -0,0 +1,4 @@ +import { shellSort } from '../../../../src/js/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(shellSort, 'Shell Sort'); diff --git a/test/js/algorithms/sorting/sort-algorithm-tests.js b/test/js/algorithms/sorting/sort-algorithm-tests.js new file mode 100644 index 00000000..6b883e83 --- /dev/null +++ b/test/js/algorithms/sorting/sort-algorithm-tests.js @@ -0,0 +1,69 @@ +import 'mocha'; +import { expect } from 'chai'; +import { Compare } from '../../../../src/js/util'; + +export function testSortAlgorithm(sortAlgorithm, algorithmName, config = { reverseCompare: true }) { + describe(algorithmName, () => { + const SIZE = 100; + + function createNonSortedArray() { + const array = []; + for (let i = SIZE; i > 0; i--) { + array.push(i); + } + return array; + } + + function createSortedArray() { + const array = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('works with empty arrays', () => { + expect(sortAlgorithm([])).to.deep.equal([]); + }); + + it('works with sorted arrays', () => { + let array = createSortedArray(); + const sortedArray = createSortedArray(); + array = sortAlgorithm(array); + expect(array).to.deep.equal(sortedArray); + }); + + it('works with non-sorted arrays', () => { + let array = createNonSortedArray(); + const sortedArray = createSortedArray(); + array = sortAlgorithm(array); + + expect(array).to.deep.equal(sortedArray); + + for (let i = 0; i < array.length - 1; i++) { + expect(array[i] <= array[i + 1]).to.equal(true); + } + }); + + function reverseCompare(a, b) { + if (a === b) { + return 0; + } + return a < b ? Compare.BIGGER_THAN : Compare.LESS_THAN; + } + + if (config.reverseCompare) { + it('works with reverse comparator - descending order', () => { + let array = createSortedArray(); + const sortedArray = createNonSortedArray(); + array = sortAlgorithm(array, reverseCompare); + + expect(array).to.deep.equal(sortedArray); + + for (let i = 0; i < array.length - 1; i++) { + expect(array[i] >= array[i + 1]).to.equal(true); + } + }); + } + }); +} diff --git a/test/js/data-structures/avl-tree.spec.js b/test/js/data-structures/avl-tree.spec.js new file mode 100644 index 00000000..f113e561 --- /dev/null +++ b/test/js/data-structures/avl-tree.spec.js @@ -0,0 +1,32 @@ +import 'mocha'; +import { expect } from 'chai'; +import { AVLTree } from '../../../src/js/index'; + +describe('AVLTree', () => { + let tree; + + beforeEach(() => { + tree = new AVLTree(); + }); + + it('starts empty', () => { + expect(tree.getRoot()).to.equal(null); + }); + + it('inserts elements in the AVLTree', () => { + expect(tree.getRoot()).to.equal(null); + + tree.insert(1); + tree.insert(2); + tree.insert(3); + tree.insert(4); + tree.insert(5); + tree.insert(6); + tree.insert(7); + tree.insert(14); + tree.insert(15); + tree.insert(13); + tree.insert(12); + tree.insert(11); + }); +}); diff --git a/test/js/data-structures/binary-search-tree.spec.js b/test/js/data-structures/binary-search-tree.spec.js new file mode 100644 index 00000000..8b940818 --- /dev/null +++ b/test/js/data-structures/binary-search-tree.spec.js @@ -0,0 +1,108 @@ +import 'mocha'; +import { expect } from 'chai'; +import { BinarySearchTree } from '../../../src/js/index'; + +describe('BinarySearchTree', () => { + let tree; + + beforeEach(() => { + tree = new BinarySearchTree(); + }); + + it('starts empty', () => { + expect(tree.getRoot()).to.equal(undefined); + }); + + function assertNode(node, key, left, right) { + if (key != null) { + expect(node.key).to.equal(key); + } else { + expect(node).to.equal(key); + return; + } + + if (left != null) { + expect(node.left.key).to.equal(left); + } else { + expect(node.left).to.equal(left); + } + + if (right != null) { + expect(node.right.key).to.equal(right); + } else { + expect(node.right).to.equal(right); + } + } + + it('inserts elements in the BST', () => { + expect(tree.getRoot()).to.equal(undefined); + + tree.insert(11); + tree.insert(7); + tree.insert(15); + tree.insert(5); + tree.insert(3); + tree.insert(9); + tree.insert(8); + tree.insert(10); + tree.insert(13); + tree.insert(12); + tree.insert(14); + tree.insert(20); + tree.insert(18); + tree.insert(25); + + let node = tree.getRoot(); + assertNode(node, 11, 7, 15); + + node = node.left; + assertNode(node, 7, 5, 9); + + node = node.left; + assertNode(node, 5, 3, undefined); + + node = node.left; + assertNode(node, 3, undefined, undefined); + + node = tree.getRoot().left.left.right; + assertNode(node, undefined, undefined, undefined); + + node = tree.getRoot().left.right; + assertNode(node, 9, 8, 10); + + node = node.left; + assertNode(node, 8, undefined, undefined); + + node = tree.getRoot().left.right.right; + assertNode(node, 10, undefined, undefined); + + node = tree.getRoot().right; + assertNode(node, 15, 13, 20); + + node = node.left; + assertNode(node, 13, 12, 14); + + node = node.left; + assertNode(node, 12, undefined, undefined); + + node = tree.getRoot().right.left.right; + assertNode(node, 14, undefined, undefined); + + node = tree.getRoot().right.right; + assertNode(node, 20, 18, 25); + + node = node.left; + assertNode(node, 18, undefined, undefined); + + node = tree.getRoot().right.right.right; + assertNode(node, 25, undefined, undefined); + }); + + it('verifies if element exists', () => { + expect(tree.getRoot()).to.equal(undefined); + }); + + it('removes a leaf', () => { + expect(tree.getRoot()).to.equal(undefined); + }); +}); diff --git a/test/js/data-structures/circular-linked-list.spec.js b/test/js/data-structures/circular-linked-list.spec.js new file mode 100644 index 00000000..aadb02ee --- /dev/null +++ b/test/js/data-structures/circular-linked-list.spec.js @@ -0,0 +1,342 @@ +import 'mocha'; +import { expect } from 'chai'; +import { CircularLinkedList } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('CircularLinkedList', () => { + let list; + let min; + let max; + + beforeEach(() => { + list = new CircularLinkedList(); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = min; i <= max; i++) { + list.push(i); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max && current; i++) { + expect(current).to.not.be.an('undefined'); + if (current) { + // TS strictNullChecks + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + // TS strictNullChecks + expect(current.next.element).to.equal(i + 1); + } + } else { + // circular list + expect(current.next).to.not.be.an('undefined'); + expect(current.next).to.equal(list.getHead()); + if (current.next) { + expect(current.next.element).to.equal(min); + } + } + current = current.next; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max, 0)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + expect(list.insert(1, 1)).to.equal(false); + }); + + it('inserts elements invalid position not empty list', () => { + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(false); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i, i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + const minIndex = min; + for (let i = minIndex; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + min++; + verifyList(); + } + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(min); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(max); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(max); + expect(current.next).to.not.be.an('undefined'); + expect(current.next).to.equal(list.getHead()); + if (current.next) { + expect(current.next.element).to.equal(min); + } + } + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new CircularLinkedList(); + ds.push('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new CircularLinkedList(); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/deque.spec.js b/test/js/data-structures/deque.spec.js new file mode 100644 index 00000000..49ab2dfa --- /dev/null +++ b/test/js/data-structures/deque.spec.js @@ -0,0 +1,208 @@ +import 'mocha'; +import { expect } from 'chai'; +import Deque from '../../../src/js/data-structures/deque'; + +describe('Deque', () => { + let deque; + + beforeEach(() => { + deque = new Deque(); + }); + + it('starts empty', () => { + expect(deque.size()).to.equal(0); + expect(deque.isEmpty()).to.equal(true); + }); + + it('add elements in the back', () => { + deque.addBack(1); + expect(deque.size()).to.equal(1); + + deque.addBack(2); + expect(deque.size()).to.equal(2); + + deque.addBack(3); + expect(deque.size()).to.equal(3); + }); + + it('add elements in the front', () => { + deque.addFront(1); + expect(deque.size()).to.equal(1); + + deque.addFront(2); + expect(deque.size()).to.equal(2); + + deque.addFront(3); + expect(deque.size()).to.equal(3); + + deque.removeFront(); + deque.addFront(4); + expect(deque.size()).to.equal(3); + }); + + it('remove elements from the back', () => { + deque.addBack(1); + deque.addBack(2); + deque.addBack(3); + deque.addFront(0); + + expect(deque.removeBack()).to.equal(3); + expect(deque.removeBack()).to.equal(2); + expect(deque.removeBack()).to.equal(1); + expect(deque.removeBack()).to.equal(0); + expect(deque.removeBack()).to.equal(undefined); + }); + + it('remove elements from the front', () => { + deque.addFront(1); + deque.addBack(2); + deque.addBack(3); + deque.addFront(0); + deque.addFront(-1); + deque.addFront(-2); + + expect(deque.removeFront()).to.equal(-2); + expect(deque.removeFront()).to.equal(-1); + expect(deque.removeFront()).to.equal(0); + expect(deque.removeFront()).to.equal(1); + expect(deque.removeFront()).to.equal(2); + expect(deque.removeFront()).to.equal(3); + expect(deque.removeFront()).to.equal(undefined); + }); + + it('allows to peek at the front element in the deque without removing it', () => { + expect(deque.peekFront()).to.equal(undefined); + + deque.addFront(1); + expect(deque.peekFront()).to.equal(1); + deque.addBack(2); + expect(deque.peekFront()).to.equal(1); + deque.addBack(3); + expect(deque.peekFront()).to.equal(1); + deque.addFront(0); + expect(deque.peekFront()).to.equal(0); + deque.addFront(-1); + expect(deque.peekFront()).to.equal(-1); + deque.addFront(-2); + expect(deque.peekFront()).to.equal(-2); + }); + + it('allows to peek at the last element in the deque without removing it', () => { + expect(deque.peekBack()).to.equal(undefined); + + deque.addFront(1); + expect(deque.peekBack()).to.equal(1); + deque.addBack(2); + expect(deque.peekBack()).to.equal(2); + deque.addBack(3); + expect(deque.peekBack()).to.equal(3); + deque.addFront(0); + expect(deque.peekBack()).to.equal(3); + deque.addFront(-1); + expect(deque.peekBack()).to.equal(3); + deque.addFront(-2); + expect(deque.peekBack()).to.equal(3); + }); + + it('returns the correct size', () => { + expect(deque.size()).to.equal(0); + + deque.addFront(1); + expect(deque.size()).to.equal(1); + deque.addBack(2); + expect(deque.size()).to.equal(2); + deque.addBack(3); + expect(deque.size()).to.equal(3); + deque.addFront(0); + expect(deque.size()).to.equal(4); + deque.addFront(-1); + expect(deque.size()).to.equal(5); + deque.addFront(-2); + expect(deque.size()).to.equal(6); + + deque.clear(); + expect(deque.size()).to.equal(0); + + deque.addFront(1); + deque.addBack(2); + expect(deque.size()).to.equal(2); + + deque.removeFront(); + deque.removeBack(); + expect(deque.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(deque.isEmpty()).to.equal(true); + + deque.addFront(1); + expect(deque.isEmpty()).to.equal(false); + deque.addBack(2); + expect(deque.isEmpty()).to.equal(false); + + deque.clear(); + expect(deque.isEmpty()).to.equal(true); + + deque.addFront(1); + deque.addBack(2); + expect(deque.isEmpty()).to.equal(false); + + deque.removeFront(); + expect(deque.isEmpty()).to.equal(false); + deque.removeBack(); + expect(deque.isEmpty()).to.equal(true); + }); + + it('clears the queue', () => { + deque.clear(); + expect(deque.isEmpty()).to.equal(true); + + deque.addFront(1); + deque.addBack(2); + expect(deque.isEmpty()).to.equal(false); + + deque.clear(); + expect(deque.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(deque.toString()).to.equal(''); + + deque.addFront(1); + expect(deque.toString()).to.equal('1'); + + deque.addBack(2); + expect(deque.toString()).to.equal('1,2'); + + deque.clear(); + expect(deque.toString()).to.equal(''); + + const queueString = new Deque(); + queueString.addFront('el1'); + expect(queueString.toString()).to.equal('el1'); + + queueString.addBack('el2'); + expect(queueString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + class MyObj { + constructor(el1, el2) { + this.el1 = el1; + this.el2 = el2; + } + + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + const dequeMyObj = new Deque(); + expect(dequeMyObj.toString()).to.equal(''); + + dequeMyObj.addFront(new MyObj(1, 2)); + expect(dequeMyObj.toString()).to.equal('1|2'); + + dequeMyObj.addBack(new MyObj(3, 4)); + expect(dequeMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/dictionary.spec.js b/test/js/data-structures/dictionary.spec.js new file mode 100644 index 00000000..72e78640 --- /dev/null +++ b/test/js/data-structures/dictionary.spec.js @@ -0,0 +1,266 @@ +import 'mocha'; +import { expect } from 'chai'; +import { Dictionary } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('Dictionary', () => { + let dictionary; + beforeEach(() => { + dictionary = new Dictionary(); + }); + it('starts empty', () => { + expect(dictionary.size()).to.equal(0); + expect(dictionary.isEmpty()).to.equal(true); + }); + it('sets undefined and null keys and values', () => { + const dict = new Dictionary(); + expect(dict.set('undefined', undefined)).to.equal(false); + expect(dict.get('undefined')).to.equal(undefined); + expect(dict.set('undefined', 1)).to.equal(true); + expect(dict.get('undefined')).to.equal(1); + expect(dict.set('null', null)).to.equal(false); + expect(dict.get('null')).to.equal(undefined); + expect(dict.set('null', 1)).to.equal(true); + expect(dict.get('null')).to.equal(1); + dict.clear(); + expect(dict.set(undefined, undefined)).to.equal(false); + expect(dict.get(undefined)).to.equal(undefined); + expect(dict.set(undefined, 1)).to.equal(false); + expect(dict.get(undefined)).to.equal(undefined); + expect(dict.set(null, null)).to.equal(false); + expect(dict.get(null)).to.equal(undefined); + expect(dict.set(null, 1)).to.equal(false); + expect(dict.get(null)).to.equal(undefined); + }); + it('sets values with string key', () => { + const dict = new Dictionary(); + const min = 1; + const max = 5; + const size = (max - min) + 1; + for (let i = min; i <= max; i++) { + expect(dict.set(`${i}`, i)).to.equal(true); + } + expect(dict.size()).to.equal(size); + const keys = dict.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal((i + 1).toString(10)); + } + dict.set('a', 1); + expect(dict.get('a')).to.equal(1); + }); + it('sets values with number key', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + const keys = dictionary.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal(i + 1); + } + }); + it('sets values with object', () => { + const dict = new Dictionary(); + const min = 0; + const max = 5; + const size = max - min; + const myObjList = []; + for (let i = min; i < max; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + for (let i = min; i < max; i++) { + expect(dict.set(myObjList[i], myObjList[i])).to.equal(true); + } + expect(dict.size()).to.equal(size); + for (let i = min; i < max; i++) { + expect(dict.get(myObjList[i])).to.equal(myObjList[i]); + } + const keys = dict.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal(myObjList[i]); + } + const values = dict.values(); + expect(values.length).to.equal(size); + for (let i = 0; i < values.length; i++) { + expect(values[i]).to.equal(myObjList[i]); + } + }); + function customToString(key) { + return `####${key.toString()}`; + } + it('sets values with custom toString function', () => { + const dict = new Dictionary(customToString); + const min = 0; + const max = 5; + const size = max - min; + const myObjList = []; + for (let i = min; i < max; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + for (let i = min; i < max; i++) { + expect(dict.set(myObjList[i], myObjList[i])).to.equal(true); + } + expect(dict.size()).to.equal(size); + for (let i = min; i < max; i++) { + expect(dict.get(myObjList[i])).to.equal(myObjList[i]); + } + const keys = dict.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal(myObjList[i]); + } + const values = dict.values(); + expect(values.length).to.equal(size); + for (let i = 0; i < values.length; i++) { + expect(values[i]).to.equal(myObjList[i]); + } + }); + it('removes elements', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(dictionary.remove(i)).to.equal(true); + } + // elements do not exist + for (let i = min; i <= max; i++) { + expect(dictionary.remove(i)).to.equal(false); + } + expect(dictionary.isEmpty()).to.equal(true); + }); + it('returns the correct size', () => { + expect(dictionary.size()).to.equal(0); + const max = 5; + for (let i = 1; i < max; i++) { + dictionary.set(i, i); + expect(dictionary.size()).to.equal(i); + } + for (let i = 1; i < max; i++) { + dictionary.remove(i); + expect(dictionary.size()).to.equal(max - i - 1); + } + expect(dictionary.size()).to.equal(0); + expect(dictionary.isEmpty()).to.equal(true); + }); + it('returns if element exists', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(dictionary.hasKey(i)).to.equal(true); + expect(dictionary.remove(i)).to.equal(true); + expect(dictionary.hasKey(i)).to.equal(false); + } + }); + it('returns if it is empty', () => { + expect(dictionary.isEmpty()).to.equal(true); + for (let i = 1; i < 5; i++) { + dictionary.set(i, i); + expect(dictionary.isEmpty()).to.equal(false); + } + for (let i = 1; i < 5; i++) { + dictionary.remove(i); + expect(dictionary.isEmpty()).to.equal(!(i < 4)); + } + expect(dictionary.size()).to.equal(0); + expect(dictionary.isEmpty()).to.equal(true); + }); + it('clears the dictionary', () => { + dictionary.clear(); + expect(dictionary.isEmpty()).to.equal(true); + dictionary.set(1, 1); + dictionary.set(2, 2); + dictionary.clear(); + expect(dictionary.isEmpty()).to.equal(true); + }); + it('returns values, keys and value pairs', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + const keys = dictionary.keys(); + const values = dictionary.values(); + const valuePairs = dictionary.keyValues(); + expect(keys.length).to.equal(size); + expect(values.length).to.equal(size); + expect(valuePairs.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal(i + 1); + expect(values[i]).to.equal(i + 1); + expect(valuePairs[i].key).to.equal(i + 1); + expect(valuePairs[i].value).to.equal(i + 1); + } + }); + it('allows to iterate with forEach', () => { + for (let i = 1; i <= 5; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + dictionary.forEach((k, v) => { + expect(dictionary.hasKey(k)).to.equal(true); + expect(dictionary.get(k)).to.equal(v); + }); + }); + it('allows to iterate with forEach and interrupt', () => { + for (let i = 1; i <= 5; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + const size = dictionary.keys().length; + let index = 1; + dictionary.forEach((k, v) => { + expect(dictionary.hasKey(k)).to.equal(true); + expect(dictionary.get(k)).to.equal(v); + index++; + }); + expect(index).to.equal(size + 1); + index = 1; + dictionary.forEach((k, v) => { + expect(dictionary.hasKey(k)).to.equal(true); + expect(dictionary.get(k)).to.equal(v); + index++; + return !(k % 3 === 0); + }); + expect(index).to.equal(size - 1); + }); + it('returns toString primitive types', () => { + expect(dictionary.toString()).to.equal(''); + dictionary.set(1, 1); + expect(dictionary.toString()).to.equal('[#1: 1]'); + dictionary.set(2, 2); + expect(dictionary.toString()).to.equal('[#1: 1],[#2: 2]'); + dictionary.clear(); + expect(dictionary.toString()).to.equal(''); + }); + it('returns toString primitive types: string', () => { + const dict = new Dictionary(); + dict.set('el1', 1); + expect(dict.toString()).to.equal('[#el1: 1]'); + dict.set('el2', 2); + expect(dict.toString()).to.equal('[#el1: 1],[#el2: 2]'); + }); + it('returns toString objects', () => { + const dict = new Dictionary(); + expect(dict.toString()).to.equal(''); + let myObj = new MyObj(1, 2); + dict.set(myObj, myObj); + expect(dict.toString()).to.equal('[#1|2: 1|2]'); + myObj = new MyObj(3, 4); + dict.set(myObj, myObj); + expect(dict.toString()).to.equal('[#1|2: 1|2],[#3|4: 3|4]'); + }); +}); diff --git a/test/js/data-structures/doubly-linked-list.spec.js b/test/js/data-structures/doubly-linked-list.spec.js new file mode 100644 index 00000000..5e7fd6a4 --- /dev/null +++ b/test/js/data-structures/doubly-linked-list.spec.js @@ -0,0 +1,406 @@ +import 'mocha'; +import { expect } from 'chai'; +import { DoublyLinkedList } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('DoublyLinkedList', () => { + let list; + let min; + let max; + + beforeEach(() => { + list = new DoublyLinkedList(); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = min; i <= max; i++) { + list.push(i); + } + } + + function verifyNode(current, i) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + + // verify next node + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + // TS strictNullChecks + if (current.next) { + expect(current.next.element).to.equal(i + 1); + } + } else { + expect(current.next).to.be.an('undefined'); + } + + // verify previous node + if (i > min) { + expect(current.prev).to.not.be.an('undefined'); + if (current.prev) { + expect(current.prev.element).to.equal(i - 1); + } + } else { + expect(current.prev).to.be.an('undefined'); + } + } + + function verifyListFromTail() { + let current = list.getTail(); + for (let i = max; i >= min; i--) { + expect(current).to.not.be.an('undefined'); + // TS strictNullChecks + if (current) { + verifyNode(current, i); + current = current.prev; + } + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max; i++) { + expect(current).to.not.be.an('undefined'); + // TS strictNullChecks + if (current) { + verifyNode(current, i); + current = current.next; + } + } + verifyListFromTail(); + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + expect(list.getTail()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max, 0)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + expect(list.insert(1, 1)).to.equal(false); + }); + + it('inserts elements invalid position not empty list', () => { + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(false); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i, i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + for (let i = min; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.getTail()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(1); + expect(current.prev).to.be.an('undefined'); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(3); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(3); + expect(current.next).to.be.an('undefined'); + expect(current.prev).to.not.be.an('undefined'); + if (current.prev) { + expect(current.prev.element).to.equal(1); + } + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the tail of the list', () => { + expect(list.getTail()).to.be.an('undefined'); + + list.push(1); + expect(list.getTail()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new DoublyLinkedList(); + ds.push('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new DoublyLinkedList(); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); + + it('returns inverseToString primitive types', () => { + expect(list.inverseToString()).to.equal(''); + + list.push(1); + expect(list.inverseToString()).to.equal('1'); + + list.push(2); + expect(list.inverseToString()).to.equal('2,1'); + + list.clear(); + expect(list.inverseToString()).to.equal(''); + }); + + it('returns inverseToString primitive types: string', () => { + const ds = new DoublyLinkedList(); + ds.push('el1'); + expect(ds.inverseToString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.inverseToString()).to.equal('el2,el1'); + }); + + it('returns inverseToString objects', () => { + const ds = new DoublyLinkedList(); + expect(ds.inverseToString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.inverseToString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.inverseToString()).to.equal('3|4,1|2'); + }); +}); diff --git a/test/js/data-structures/hash-table-linear-probing-lazy.spec.js b/test/js/data-structures/hash-table-linear-probing-lazy.spec.js new file mode 100644 index 00000000..f7dd7e06 --- /dev/null +++ b/test/js/data-structures/hash-table-linear-probing-lazy.spec.js @@ -0,0 +1,300 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTableLinearProbingLazy } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('HashTableLinearProbingLazy', () => { + const A = 'Jonathan'; + const B = 'Jamie'; + const C = 'Sue'; + it('starts empty', () => { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + it('generates hashcode', () => { + // numbers + let hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + // strings + hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + // objects + hashTable = new HashTableLinearProbingLazy(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + it('puts undefined and null keys and values', () => { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + it('puts values with number key without collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableLinearProbingLazy(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + } + }); + it('puts values with string key without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + const table = hashTable.getTable(); + expect(table[12].key).to.equal('1'); + expect(table[12].value).to.equal(1); + expect(table[23].key).to.equal('10'); + expect(table[23].value).to.equal(10); + expect(table[34].key).to.equal('100'); + expect(table[34].value).to.equal(100); + expect(table[8].key).to.equal('1000'); + expect(table[8].value).to.equal(1000); + }); + it('puts values with object key without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + const table = hashTable.getTable(); + expect(table[1].key).to.equal(myObjList[0]); + expect(table[1].value).to.equal(myObjList[0]); + expect(table[3].key).to.equal(myObjList[1]); + expect(table[3].value).to.equal(myObjList[1]); + expect(table[5].key).to.equal(myObjList[2]); + expect(table[5].value).to.equal(myObjList[2]); + expect(table[7].key).to.equal(myObjList[3]); + expect(table[7].value).to.equal(myObjList[3]); + expect(table[9].key).to.equal(myObjList[4]); + expect(table[9].value).to.equal(myObjList[4]); + }); + function addValuesCollision() { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.size()).to.equal(3); + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.size()).to.equal(3); + return hashTable; + } + it('puts values with collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableLinearProbingLazy(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 10)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 2); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 100)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 3); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + expect(table[i + size].key).to.equal(i); + expect(table[i + size].value).to.equal(i + 10); + expect(table[i + (size * 2)].key).to.equal(i); + expect(table[i + (size * 2)].value).to.equal(i + 100); + } + addValuesCollision(); + }); + it('removes elements without collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableLinearProbingLazy(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + expect(hashTable.isEmpty()).to.equal(true); + }); + function removeWithCollision(a, b, c) { + const hashTable = addValuesCollision(); + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + expect(hashTable.isEmpty()).to.equal(true); + } + it('removes elements with collisions: scenario 1', () => { + // test all possibilities for removal + removeWithCollision(A, B, C); + removeWithCollision(A, C, B); + removeWithCollision(B, A, C); + removeWithCollision(B, C, A); + removeWithCollision(C, A, B); + removeWithCollision(C, B, A); + }); + function addValuesCollision2() { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.put(')', 'parenthesis@email.com')).to.equal(true); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put('+', 'plus@email.com')).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(',', 'comma@email.com')).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.put('-', 'minus@email.com')).to.equal(true); + expect(hashTable.put('0', 'zero@email.com')).to.equal(true); + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.hashCode(')')).to.equal(4); + expect(hashTable.hashCode('+')).to.equal(6); + expect(hashTable.hashCode(',')).to.equal(7); + expect(hashTable.hashCode('-')).to.equal(8); + expect(hashTable.hashCode('0')).to.equal(11); + expect(hashTable.size()).to.equal(8); + const table = hashTable.getTable(); + expect(table[4].key).to.equal(')'); + expect(table[5].key).to.equal(A); + expect(table[6].key).to.equal('+'); + expect(table[7].key).to.equal(B); + expect(table[8].key).to.equal(','); + expect(table[9].key).to.equal(C); + expect(table[10].key).to.equal('-'); + expect(table[11].key).to.equal('0'); + return hashTable; + } + function verifyOtherKeys(hashTable) { + expect(hashTable.get(')')).to.not.equal(undefined); + expect(hashTable.get('+')).to.not.equal(undefined); + expect(hashTable.get(',')).to.not.equal(undefined); + expect(hashTable.get('-')).to.not.equal(undefined); + expect(hashTable.get('0')).to.not.equal(undefined); + } + function removeWithCollision2(a, b, c) { + const hashTable = addValuesCollision2(); + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + verifyOtherKeys(hashTable); + } + it('removes elements with collisions: scenario 2', () => { + // test all possibilities for removal + removeWithCollision2(A, B, C); + removeWithCollision2(A, C, B); + removeWithCollision2(B, A, C); + removeWithCollision2(B, C, A); + removeWithCollision2(C, A, B); + removeWithCollision2(C, B, A); + }); + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + it('returns toString objects without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}'); + }); + it('returns toString with collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.put(1, 10); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]},{3 => [#1: 10]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); +}); diff --git a/test/js/data-structures/hash-table-linear-probing.spec.js b/test/js/data-structures/hash-table-linear-probing.spec.js new file mode 100644 index 00000000..bfb519f3 --- /dev/null +++ b/test/js/data-structures/hash-table-linear-probing.spec.js @@ -0,0 +1,300 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTableLinearProbing } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('HashTableLinearProbing', () => { + const A = 'Jonathan'; + const B = 'Jamie'; + const C = 'Sue'; + it('starts empty', () => { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + it('generates hashcode', () => { + // numbers + let hashTable = new HashTableLinearProbing(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + // strings + hashTable = new HashTableLinearProbing(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + // objects + hashTable = new HashTableLinearProbing(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + it('puts undefined and null keys and values', () => { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + it('puts values with number key without collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableLinearProbing(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + } + }); + it('puts values with string key without collisions', () => { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + const table = hashTable.getTable(); + expect(table[12].key).to.equal('1'); + expect(table[12].value).to.equal(1); + expect(table[23].key).to.equal('10'); + expect(table[23].value).to.equal(10); + expect(table[34].key).to.equal('100'); + expect(table[34].value).to.equal(100); + expect(table[8].key).to.equal('1000'); + expect(table[8].value).to.equal(1000); + }); + it('puts values with object key without collisions', () => { + const hashTable = new HashTableLinearProbing(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + const table = hashTable.getTable(); + expect(table[1].key).to.equal(myObjList[0]); + expect(table[1].value).to.equal(myObjList[0]); + expect(table[3].key).to.equal(myObjList[1]); + expect(table[3].value).to.equal(myObjList[1]); + expect(table[5].key).to.equal(myObjList[2]); + expect(table[5].value).to.equal(myObjList[2]); + expect(table[7].key).to.equal(myObjList[3]); + expect(table[7].value).to.equal(myObjList[3]); + expect(table[9].key).to.equal(myObjList[4]); + expect(table[9].value).to.equal(myObjList[4]); + }); + function addValuesCollision() { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.size()).to.equal(3); + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.size()).to.equal(3); + return hashTable; + } + it('puts values with collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableLinearProbing(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 10)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 2); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 100)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 3); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + expect(table[i + size].key).to.equal(i); + expect(table[i + size].value).to.equal(i + 10); + expect(table[i + (size * 2)].key).to.equal(i); + expect(table[i + (size * 2)].value).to.equal(i + 100); + } + addValuesCollision(); + }); + it('removes elements without collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableLinearProbing(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + expect(hashTable.isEmpty()).to.equal(true); + }); + function removeWithCollision(a, b, c) { + const hashTable = addValuesCollision(); + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + expect(hashTable.isEmpty()).to.equal(true); + } + it('removes elements with collisions: scenario 1', () => { + // test all possibilities for removal + removeWithCollision(A, B, C); + removeWithCollision(A, C, B); + removeWithCollision(B, A, C); + removeWithCollision(B, C, A); + removeWithCollision(C, A, B); + removeWithCollision(C, B, A); + }); + function addValuesCollision2() { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.put(')', 'parenthesis@email.com')).to.equal(true); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put('+', 'plus@email.com')).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(',', 'comma@email.com')).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.put('-', 'minus@email.com')).to.equal(true); + expect(hashTable.put('0', 'zero@email.com')).to.equal(true); + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.hashCode(')')).to.equal(4); + expect(hashTable.hashCode('+')).to.equal(6); + expect(hashTable.hashCode(',')).to.equal(7); + expect(hashTable.hashCode('-')).to.equal(8); + expect(hashTable.hashCode('0')).to.equal(11); + expect(hashTable.size()).to.equal(8); + const table = hashTable.getTable(); + expect(table[4].key).to.equal(')'); + expect(table[5].key).to.equal(A); + expect(table[6].key).to.equal('+'); + expect(table[7].key).to.equal(B); + expect(table[8].key).to.equal(','); + expect(table[9].key).to.equal(C); + expect(table[10].key).to.equal('-'); + expect(table[11].key).to.equal('0'); + return hashTable; + } + function verifyOtherKeys(hashTable) { + expect(hashTable.get(')')).to.not.equal(undefined); + expect(hashTable.get('+')).to.not.equal(undefined); + expect(hashTable.get(',')).to.not.equal(undefined); + expect(hashTable.get('-')).to.not.equal(undefined); + expect(hashTable.get('0')).to.not.equal(undefined); + } + function removeWithCollision2(a, b, c) { + const hashTable = addValuesCollision2(); + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + verifyOtherKeys(hashTable); + } + it('removes elements with collisions: scenario 2', () => { + // test all possibilities for removal + removeWithCollision2(A, B, C); + removeWithCollision2(A, C, B); + removeWithCollision2(B, A, C); + removeWithCollision2(B, C, A); + removeWithCollision2(C, A, B); + removeWithCollision2(C, B, A); + }); + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbing(); + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + it('returns toString objects without collisions', () => { + const hashTable = new HashTableLinearProbing(); + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}'); + }); + it('returns toString with collisions', () => { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.put(1, 10); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]},{3 => [#1: 10]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); +}); diff --git a/test/js/data-structures/hash-table-separate-chaining.spec.js b/test/js/data-structures/hash-table-separate-chaining.spec.js new file mode 100644 index 00000000..2066c2d0 --- /dev/null +++ b/test/js/data-structures/hash-table-separate-chaining.spec.js @@ -0,0 +1,269 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTableSeparateChaining } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('HashTableSeparateChaining', () => { + const A = 'Jonathan'; + const B = 'Jamie'; + const C = 'Sue'; + it('starts empty', () => { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + it('generates hashcode', () => { + // numbers + let hashTable = new HashTableSeparateChaining(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + // strings + hashTable = new HashTableSeparateChaining(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + // objects + hashTable = new HashTableSeparateChaining(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + it('puts undefined and null keys and values', () => { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + it('puts values with number key without collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableSeparateChaining(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + const linkedList = table[i]; + expect(linkedList.size()).to.equal(1); + const valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i); + } + }); + it('puts values with string key without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + const table = hashTable.getTable(); + let linkedList = table[12]; + expect(linkedList.size()).to.equal(1); + let valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('1'); + expect(valuePair.element.value).to.equal(1); + linkedList = table[23]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('10'); + expect(valuePair.element.value).to.equal(10); + linkedList = table[34]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('100'); + expect(valuePair.element.value).to.equal(100); + linkedList = table[8]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('1000'); + expect(valuePair.element.value).to.equal(1000); + }); + it('puts values with object key without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + const table = hashTable.getTable(); + let linkedList = table[1]; + expect(linkedList.size()).to.equal(1); + let valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[0]); + expect(valuePair.element.value).to.equal(myObjList[0]); + linkedList = table[3]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[1]); + expect(valuePair.element.value).to.equal(myObjList[1]); + linkedList = table[5]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[2]); + expect(valuePair.element.value).to.equal(myObjList[2]); + linkedList = table[7]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[3]); + expect(valuePair.element.value).to.equal(myObjList[3]); + linkedList = table[9]; // eslint-disable-line prefer-destructuring + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[4]); + expect(valuePair.element.value).to.equal(myObjList[4]); + }); + it('puts values with collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableSeparateChaining(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 10)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 2); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 100)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 3); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + const linkedList = table[i]; + expect(linkedList.size()).to.equal(3); + let valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i); + valuePair = valuePair.next; + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i + 10); + valuePair = valuePair.next; + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i + 100); + } + }); + it('removes elements without collisions', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTableSeparateChaining(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + expect(hashTable.isEmpty()).to.equal(true); + }); + function addValuesCollision() { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.size()).to.equal(3); + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.getTable()[expectedHash].size()).to.equal(3); + return hashTable; + } + function removeWithCollision(a, b, c) { + const hashTable = addValuesCollision(); + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + expect(hashTable.isEmpty()).to.equal(true); + } + it('removes elements with collisions', () => { + // test all possibilities for removal + removeWithCollision(A, B, C); + removeWithCollision(A, C, B); + removeWithCollision(B, A, C); + removeWithCollision(B, C, A); + removeWithCollision(C, A, B); + removeWithCollision(C, B, A); + }); + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + it('returns toString objects without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}'); + }); + it('returns toString with collisions', () => { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.put(1, 10); + expect(hashTable.toString()).to.equal('{1 => [#1: 1],[#1: 10]},{2 => [#2: 2]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); +}); diff --git a/test/js/data-structures/hash-table.spec.js b/test/js/data-structures/hash-table.spec.js new file mode 100644 index 00000000..862c9be0 --- /dev/null +++ b/test/js/data-structures/hash-table.spec.js @@ -0,0 +1,161 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTable } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('HashTable', () => { + it('starts empty', () => { + const hashTable = new HashTable(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + it('generates hashcode', () => { + // numbers + let hashTable = new HashTable(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + // strings + hashTable = new HashTable(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + // objects + hashTable = new HashTable(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + it('puts undefined and null keys and values', () => { + const hashTable = new HashTable(); + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + it('puts values with number key', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTable(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + } + }); + it('puts values with string key', () => { + const hashTable = new HashTable(); + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + const table = hashTable.getTable(); + expect(table[12].key).to.equal('1'); + expect(table[12].value).to.equal(1); + expect(table[23].key).to.equal('10'); + expect(table[23].value).to.equal(10); + expect(table[34].key).to.equal('100'); + expect(table[34].value).to.equal(100); + expect(table[8].key).to.equal('1000'); + expect(table[8].value).to.equal(1000); + }); + it('puts values with object key', () => { + const hashTable = new HashTable(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + const table = hashTable.getTable(); + expect(table[1].key).to.equal(myObjList[0]); + expect(table[1].value).to.equal(myObjList[0]); + expect(table[3].key).to.equal(myObjList[1]); + expect(table[3].value).to.equal(myObjList[1]); + expect(table[5].key).to.equal(myObjList[2]); + expect(table[5].value).to.equal(myObjList[2]); + expect(table[7].key).to.equal(myObjList[3]); + expect(table[7].value).to.equal(myObjList[3]); + expect(table[9].key).to.equal(myObjList[4]); + expect(table[9].value).to.equal(myObjList[4]); + }); + it('does NOT handle collision, replaces values', () => { + const hashTable = new HashTable(); + for (let i = 0; i < 5; i++) { + expect(hashTable.put(1, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(1); + }); + it('removes elements', () => { + const min = 1; + const max = 5; + const size = (max - min) + 1; + const hashTable = new HashTable(); + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + expect(hashTable.isEmpty()).to.equal(true); + }); + it('returns toString primitive types', () => { + const hashTable = new HashTable(); + expect(hashTable.toString()).to.equal(''); + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + it('returns toString primitive types', () => { + const hashTable = new HashTable(); + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + it('returns toString objects', () => { + const hashTable = new HashTable(); + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}'); + }); +}); diff --git a/test/js/data-structures/heap.spec.js b/test/js/data-structures/heap.spec.js new file mode 100644 index 00000000..15ce1bce --- /dev/null +++ b/test/js/data-structures/heap.spec.js @@ -0,0 +1,75 @@ +import 'mocha'; +import { expect } from 'chai'; +import { MinHeap, heapSort } from '../../../src/js/index'; + +describe('Heap', () => { + let heap; + + beforeEach(() => { + heap = new MinHeap(); + }); + + it('starts empty MinHeap', () => { + expect(heap.size()).to.equal(0); + expect(heap.isEmpty()).to.equal(true); + }); + + it('inserts values in the MinHeap', () => { + const resultArray = []; + for (let i = 1; i < 10; i++) { + resultArray.push(i); + heap.insert(i); + expect(heap.getAsArray()).to.deep.equal(resultArray); + } + }); + + it('finds the min value from the MinHeap', () => { + const resultArray = []; + for (let i = 10; i >= 1; i--) { + resultArray.push(i); + heap.insert(i); + expect(heap.findMinimum()).to.equal(i); + } + }); + + it('performs heapify in the MinHeap', () => { + const resultArray = []; + for (let i = 10; i >= 1; i--) { + resultArray.push(i); + } + expect(heap.heapify(resultArray)).to.deep.equal(resultArray); + }); + + it('extracts the min value from the MinHeap', () => { + let resultArray = []; + for (let i = 1; i < 10; i++) { + resultArray.push(i); + heap.insert(i); + expect(heap.getAsArray()).to.deep.equal(resultArray); + } + + resultArray = [ + [], + [2, 4, 3, 8, 5, 6, 7, 9], + [3, 4, 6, 8, 5, 9, 7], + [4, 5, 6, 8, 7, 9], + [5, 7, 6, 8, 9], + [6, 7, 9, 8], + [7, 8, 9], + [8, 9], + [9], + [] + ]; + + for (let i = 1; i < 10; i++) { + expect(heap.extract()).to.equal(i); + expect(heap.getAsArray()).to.deep.equal(resultArray[i]); + } + }); + + it('Heap Sort', () => { + const array = [3, 2, 5, 6, 1, 7, 8, 9]; + + expect(heapSort(array)).to.deep.equal([1, 2, 3, 5, 6, 7, 8, 9]); + }); +}); diff --git a/test/js/data-structures/linked-list.spec.js b/test/js/data-structures/linked-list.spec.js new file mode 100644 index 00000000..4d9f19c6 --- /dev/null +++ b/test/js/data-structures/linked-list.spec.js @@ -0,0 +1,330 @@ +import 'mocha'; +import { expect } from 'chai'; +import { LinkedList, util } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('LinkedList', () => { + let list; + let min; + let max; + + beforeEach(() => { + list = new LinkedList(util.defaultEquals); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = min; i <= max; i++) { + list.push(i); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max && current; i++) { + expect(current).to.not.be.an('undefined'); + if (current) { + // TS strictNullChecks + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + // TS strictNullChecks + expect(current.next.element).to.equal(i + 1); + } + } else { + expect(current.next).to.be.an('undefined'); + } + current = current.next; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max, 0)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + expect(list.insert(1, 1)).to.equal(false); + }); + + it('inserts elements invalid position not empty list', () => { + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(false); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i, i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + for (let i = min; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + } + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(1); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(3); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(3); + expect(current.next).to.be.an('undefined'); + } + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new LinkedList(); + ds.push('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new LinkedList(); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/my-obj.js b/test/js/data-structures/my-obj.js new file mode 100644 index 00000000..ed407894 --- /dev/null +++ b/test/js/data-structures/my-obj.js @@ -0,0 +1,10 @@ +export default class MyObj { + constructor(el1, el2) { + this.el1 = el1; + this.el2 = el2; + } + + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } +} diff --git a/test/js/data-structures/queue.spec.js b/test/js/data-structures/queue.spec.js new file mode 100644 index 00000000..84587bc1 --- /dev/null +++ b/test/js/data-structures/queue.spec.js @@ -0,0 +1,172 @@ +import 'mocha'; +import { expect } from 'chai'; +import Queue from '../../../src/js/data-structures/queue'; + +describe('Queue', () => { + let queue; + + beforeEach(() => { + queue = new Queue(); + }); + + it('starts empty', () => { + expect(queue.size()).to.equal(0); + expect(queue.isEmpty()).to.equal(true); + }); + + it('enqueues elements', () => { + queue.enqueue(1); + expect(queue.size()).to.equal(1); + queue.enqueue(2); + expect(queue.size()).to.equal(2); + queue.enqueue(3); + expect(queue.size()).to.equal(3); + + expect(queue.isEmpty()).to.equal(false); + }); + + it('dequeue elements', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + expect(queue.dequeue()).to.equal(1); + expect(queue.dequeue()).to.equal(2); + expect(queue.dequeue()).to.equal(3); + expect(queue.dequeue()).to.equal(undefined); + }); + + it('implements FIFO logic', () => { + queue.enqueue(1); + expect(queue.peek()).to.equal(1); + queue.enqueue(2); + expect(queue.peek()).to.equal(1); + queue.enqueue(3); + expect(queue.peek()).to.equal(1); + + expect(queue.dequeue()).to.equal(1); + expect(queue.dequeue()).to.equal(2); + expect(queue.dequeue()).to.equal(3); + expect(queue.dequeue()).to.equal(undefined); + }); + + it('allows to peek at the front element in the queue without dequeuing it', () => { + expect(queue.peek()).to.equal(undefined); + + queue.enqueue(1); + expect(queue.peek()).to.equal(1); + + queue.enqueue(2); + expect(queue.peek()).to.equal(1); + + queue.dequeue(); + expect(queue.peek()).to.equal(2); + }); + + it('returns the correct size', () => { + expect(queue.size()).to.equal(0); + queue.enqueue(1); + expect(queue.size()).to.equal(1); + queue.enqueue(2); + expect(queue.size()).to.equal(2); + queue.enqueue(3); + expect(queue.size()).to.equal(3); + + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.size()).to.equal(3); + + queue.dequeue(); + expect(queue.size()).to.equal(2); + queue.dequeue(); + expect(queue.size()).to.equal(1); + queue.dequeue(); + expect(queue.size()).to.equal(0); + queue.dequeue(); + expect(queue.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(queue.isEmpty()).to.equal(true); + queue.enqueue(1); + expect(queue.isEmpty()).to.equal(false); + queue.enqueue(2); + expect(queue.isEmpty()).to.equal(false); + queue.enqueue(3); + expect(queue.isEmpty()).to.equal(false); + + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.isEmpty()).to.equal(false); + + queue.dequeue(); + expect(queue.isEmpty()).to.equal(false); + queue.dequeue(); + expect(queue.isEmpty()).to.equal(false); + queue.dequeue(); + expect(queue.isEmpty()).to.equal(true); + queue.dequeue(); + expect(queue.isEmpty()).to.equal(true); + }); + + it('clears the queue', () => { + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + + queue.enqueue(1); + queue.enqueue(2); + expect(queue.isEmpty()).to.equal(false); + + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(queue.toString()).to.equal(''); + + queue.enqueue(1); + expect(queue.toString()).to.equal('1'); + + queue.enqueue(2); + expect(queue.toString()).to.equal('1,2'); + + queue.clear(); + expect(queue.toString()).to.equal(''); + + const queueString = new Queue(); + queueString.enqueue('el1'); + expect(queueString.toString()).to.equal('el1'); + + queueString.enqueue('el2'); + expect(queueString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + class MyObj { + constructor(el1, el2) { + this.el1 = el1; + this.el2 = el2; + } + + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + const queueMyObj = new Queue(); + expect(queueMyObj.toString()).to.equal(''); + + queueMyObj.enqueue(new MyObj(1, 2)); + expect(queueMyObj.toString()).to.equal('1|2'); + + queueMyObj.enqueue(new MyObj(3, 4)); + expect(queueMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/set.spec.js b/test/js/data-structures/set.spec.js new file mode 100644 index 00000000..f8e2bac1 --- /dev/null +++ b/test/js/data-structures/set.spec.js @@ -0,0 +1,352 @@ +import 'mocha'; +import { expect } from 'chai'; +import { Set } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('Set', () => { + let set; + + beforeEach(() => { + set = new Set(); + }); + + it('starts empty', () => { + expect(set.size()).to.equal(0); + expect(set.isEmpty()).to.equal(true); + }); + + it('adds elements', () => { + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.size()).to.equal(i); + } + + expect(set.isEmpty()).to.equal(false); + }); + + it('does not allow duplicated elements', () => { + let expected = true; + for (let i = 1; i < 5; i++) { + expect(set.add(i)).to.equal(expected); + } + + expected = false; + for (let i = 1; i < 5; i++) { + expect(set.add(i)).to.equal(expected); + } + }); + + it('deletes elements', () => { + for (let i = 1; i < 5; i++) { + set.add(i); + } + + for (let i = 1; i < 5; i++) { + expect(set.delete(i)).to.equal(true); + } + + // elements do not exist + for (let i = 1; i < 5; i++) { + expect(set.delete(i)).to.equal(false); + } + + expect(set.isEmpty()).to.equal(true); + }); + + it('returns if element exists', () => { + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.has(i)).to.equal(true); + } + + for (let i = 1; i < 5; i++) { + expect(set.delete(i)).to.equal(true); + expect(set.has(i)).to.equal(false); + } + }); + + it('returns the correct size', () => { + expect(set.size()).to.equal(0); + + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.size()).to.equal(i); + } + + const max = 5; + for (let i = 1; i < max; i++) { + set.delete(i); + expect(set.size()).to.equal(max - i - 1); + } + + expect(set.size()).to.equal(0); + expect(set.isEmpty()).to.equal(true); + }); + + it('returns if it is empty', () => { + expect(set.isEmpty()).to.equal(true); + + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.isEmpty()).to.equal(false); + } + + for (let i = 1; i < 5; i++) { + set.delete(i); + expect(set.isEmpty()).to.equal(!(i < 4)); + } + + expect(set.size()).to.equal(0); + expect(set.isEmpty()).to.equal(true); + }); + + it('clears the set', () => { + set.clear(); + expect(set.isEmpty()).to.equal(true); + + set.add(1); + set.add(2); + + set.clear(); + expect(set.isEmpty()).to.equal(true); + }); + + function addValues(min, max) { + set = new Set(); + + for (let i = min; i <= max; i++) { + set.add(i); + } + + return set; + } + + it('union between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + let setResult = set1.union(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.union(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('union between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + let setResult = set1.union(set2); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.union(set1); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('union between different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + let setResult = set1.union(set2); + for (let i = 1; i <= 10; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.union(set1); + for (let i = 1; i <= 10; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('union between sets with common values', () => { + const set1 = addValues(1, 5); + const set2 = addValues(3, 6); + + let setResult = set1.union(set2); + for (let i = 1; i <= 6; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.union(set1); + for (let i = 1; i <= 6; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('intersection between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + let setResult = set1.intersection(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.intersection(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('intersection between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + let setResult = set1.intersection(set2); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.intersection(set1); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('intersection different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + let setResult = set1.intersection(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.intersection(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('intersection between sets with common values', () => { + const set1 = addValues(1, 5); + const set2 = addValues(3, 6); + + let setResult = set1.intersection(set2); + for (let i = 3; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.intersection(set1); + for (let i = 3; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('difference between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + let setResult = set1.difference(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.difference(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('difference between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + let setResult = set1.difference(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.difference(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('difference different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + let setResult = set1.difference(set2); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.difference(set1); + for (let i = 6; i <= 10; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('difference between sets with common values', () => { + const set1 = addValues(1, 5); + const set2 = addValues(3, 6); + + let setResult = set1.difference(set2); + for (let i = 1; i <= 2; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.difference(set1); + for (let i = 6; i <= 6; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('isSubsetOf between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + expect(set1.isSubsetOf(set2)).to.equal(true); + expect(set2.isSubsetOf(set1)).to.equal(true); + }); + + it('isSubsetOf between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + expect(set1.isSubsetOf(set2)).to.equal(true); + expect(set2.isSubsetOf(set1)).to.equal(true); + }); + + it('isSubsetOf different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + expect(set1.isSubsetOf(set2)).to.equal(false); + expect(set2.isSubsetOf(set1)).to.equal(false); + }); + + it('isSubsetOf between sets with common values', () => { + const set1 = addValues(1, 8); + const set2 = addValues(3, 6); + expect(set1.isSubsetOf(set2)).to.equal(false); + expect(set2.isSubsetOf(set1)).to.equal(true); + + const set3 = addValues(1, 5); + const set4 = addValues(3, 6); + expect(set3.isSubsetOf(set4)).to.equal(false); + expect(set4.isSubsetOf(set3)).to.equal(false); + }); + + it('returns toString primitive types', () => { + expect(set.toString()).to.equal(''); + + set.add(1); + expect(set.toString()).to.equal('1'); + + set.add(2); + expect(set.toString()).to.equal('1,2'); + + set.clear(); + expect(set.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new Set(); + ds.add('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.add('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new Set(); + expect(ds.toString()).to.equal(''); + + ds.add(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.add(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/sorted-linked-list.spec.js b/test/js/data-structures/sorted-linked-list.spec.js new file mode 100644 index 00000000..5ccaaff9 --- /dev/null +++ b/test/js/data-structures/sorted-linked-list.spec.js @@ -0,0 +1,340 @@ +import 'mocha'; +import { expect } from 'chai'; +import { SortedLinkedList, util } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('SortedLinkedList', () => { + let list; + let min; + let max; + + beforeEach(() => { + list = new SortedLinkedList(); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = max; i >= min; i--) { + list.push(i); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max && current; i++) { + expect(current).to.not.be.an('undefined'); + if (current) { + // TS strictNullChecks + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + // TS strictNullChecks + expect(current.next.element).to.equal(i + 1); + } + } else { + expect(current.next).to.be.an('undefined'); + } + current = current.next; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + // sorted list will ignore the index position + expect(list.insert(1, 1)).to.equal(true); + }); + + it('inserts elements invalid position not empty list', () => { + // sorted list will ignore the index position + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(true); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i, i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + for (let i = min; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + } + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(1); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(3); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(3); + expect(current.next).to.be.an('undefined'); + } + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + function stringCompare(a, b) { + return a.localeCompare(b); + } + + it('returns toString primitive types: string', () => { + const ds = new SortedLinkedList(util.defaultEquals, stringCompare); + ds.push('el2'); + expect(ds.toString()).to.equal('el2'); + + ds.push('el1'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + function myObjCompare(a, b) { + return a.toString().localeCompare(b.toString()); + } + + it('returns toString objects', () => { + const ds = new SortedLinkedList(util.defaultEquals, myObjCompare); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('3|4'); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/stack-array.spec.js b/test/js/data-structures/stack-array.spec.js new file mode 100644 index 00000000..0f5912ca --- /dev/null +++ b/test/js/data-structures/stack-array.spec.js @@ -0,0 +1,181 @@ +import 'mocha'; +import { expect } from 'chai'; +import StackArray from '../../../src/js/data-structures/stack-array'; + +describe('StackArray', () => { + let stack; + + beforeEach(() => { + stack = new StackArray(); + }); + + it('starts empty', () => { + expect(stack.size()).to.equal(0); + expect(stack.isEmpty()).to.equal(true); + }); + + it('pushes elements', () => { + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + expect(stack.isEmpty()).to.equal(false); + }); + + it('pops elements', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('implements LIFO logic', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('allows to peek at the top element in he stack without popping it', () => { + expect(stack.peek()).to.equal(undefined); + + stack.push(1); + expect(stack.peek()).to.equal(1); + + stack.push(2); + expect(stack.peek()).to.equal(2); + + stack.pop(); + expect(stack.peek()).to.equal(1); + }); + + it('returns the correct size', () => { + expect(stack.size()).to.equal(0); + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.size()).to.equal(2); + stack.pop(); + expect(stack.size()).to.equal(1); + stack.pop(); + expect(stack.size()).to.equal(0); + stack.pop(); + expect(stack.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(stack.isEmpty()).to.equal(true); + stack.push(1); + expect(stack.isEmpty()).to.equal(false); + stack.push(2); + expect(stack.isEmpty()).to.equal(false); + stack.push(3); + expect(stack.isEmpty()).to.equal(false); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('clears the stack', () => { + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('returns an Array', () => { + let stackArray = stack.toArray(); + expect(stackArray.length).to.equal(0); + + stack.push(1); + stack.push(2); + + stackArray = stack.toArray(); + expect(stackArray.length).to.equal(2); + + let i = 1; + stackArray.forEach(e => { + expect(e).to.equal(i); + i++; + }); + }); + + it('returns toString primitive types', () => { + expect(stack.toString()).to.equal(''); + + stack.push(1); + expect(stack.toString()).to.equal('1'); + + stack.push(2); + expect(stack.toString()).to.equal('1,2'); + + stack.clear(); + expect(stack.toString()).to.equal(''); + + stack.push('el1'); + expect(stack.toString()).to.equal('el1'); + + stack.push('el2'); + expect(stack.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + class MyObj { + constructor(el1, el2) { + this.el1 = el1; + this.el2 = el2; + } + + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + expect(stack.toString()).to.equal(''); + + stack.push(new MyObj(1, 2)); + expect(stack.toString()).to.equal('1|2'); + + stack.push(new MyObj(3, 4)); + expect(stack.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/stack-linked-list.spec.js b/test/js/data-structures/stack-linked-list.spec.js new file mode 100644 index 00000000..19549713 --- /dev/null +++ b/test/js/data-structures/stack-linked-list.spec.js @@ -0,0 +1,157 @@ +import 'mocha'; +import { expect } from 'chai'; +import { StackLinkedList } from '../../../src/js/index'; +import MyObj from './my-obj'; + +describe('StackLinkedList', () => { + let stack; + + beforeEach(() => { + stack = new StackLinkedList(); + }); + + it('starts empty', () => { + expect(stack.size()).to.equal(0); + expect(stack.isEmpty()).to.equal(true); + }); + + it('pushes elements', () => { + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + expect(stack.isEmpty()).to.equal(false); + }); + + it('pops elements', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('implements LIFO logic', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('allows to peek at the top element in he stack without popping it', () => { + expect(stack.peek()).to.equal(undefined); + + stack.push(1); + expect(stack.peek()).to.equal(1); + + stack.push(2); + expect(stack.peek()).to.equal(2); + + stack.pop(); + expect(stack.peek()).to.equal(1); + }); + + it('returns the correct size', () => { + expect(stack.size()).to.equal(0); + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.size()).to.equal(2); + stack.pop(); + expect(stack.size()).to.equal(1); + stack.pop(); + expect(stack.size()).to.equal(0); + stack.pop(); + expect(stack.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(stack.isEmpty()).to.equal(true); + stack.push(1); + expect(stack.isEmpty()).to.equal(false); + stack.push(2); + expect(stack.isEmpty()).to.equal(false); + stack.push(3); + expect(stack.isEmpty()).to.equal(false); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('clears the stack', () => { + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(stack.toString()).to.equal(''); + + stack.push(1); + expect(stack.toString()).to.equal('1'); + + stack.push(2); + expect(stack.toString()).to.equal('1,2'); + + stack.clear(); + expect(stack.toString()).to.equal(''); + + const stackString = new StackLinkedList(); + stackString.push('el1'); + expect(stackString.toString()).to.equal('el1'); + + stackString.push('el2'); + expect(stackString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const stackMyObj = new StackLinkedList(); + expect(stackMyObj.toString()).to.equal(''); + + stackMyObj.push(new MyObj(1, 2)); + expect(stackMyObj.toString()).to.equal('1|2'); + + stackMyObj.push(new MyObj(3, 4)); + expect(stackMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/data-structures/stack.spec.js b/test/js/data-structures/stack.spec.js new file mode 100644 index 00000000..55361a8a --- /dev/null +++ b/test/js/data-structures/stack.spec.js @@ -0,0 +1,164 @@ +import 'mocha'; +import { expect } from 'chai'; +import Stack from '../../../src/js/data-structures/stack'; + +describe('Stack', () => { + let stack; + + beforeEach(() => { + stack = new Stack(); + }); + + it('starts empty', () => { + expect(stack.size()).to.equal(0); + expect(stack.isEmpty()).to.equal(true); + }); + + it('pushes elements', () => { + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + expect(stack.isEmpty()).to.equal(false); + }); + + it('pops elements', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('implements LIFO logic', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('allows to peek at the top element in he stack without popping it', () => { + expect(stack.peek()).to.equal(undefined); + + stack.push(1); + expect(stack.peek()).to.equal(1); + + stack.push(2); + expect(stack.peek()).to.equal(2); + + stack.pop(); + expect(stack.peek()).to.equal(1); + }); + + it('returns the correct size', () => { + expect(stack.size()).to.equal(0); + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.size()).to.equal(2); + stack.pop(); + expect(stack.size()).to.equal(1); + stack.pop(); + expect(stack.size()).to.equal(0); + stack.pop(); + expect(stack.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(stack.isEmpty()).to.equal(true); + stack.push(1); + expect(stack.isEmpty()).to.equal(false); + stack.push(2); + expect(stack.isEmpty()).to.equal(false); + stack.push(3); + expect(stack.isEmpty()).to.equal(false); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('clears the stack', () => { + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(stack.toString()).to.equal(''); + + stack.push(1); + expect(stack.toString()).to.equal('1'); + + stack.push(2); + expect(stack.toString()).to.equal('1,2'); + + stack.clear(); + expect(stack.toString()).to.equal(''); + + stack.push('el1'); + expect(stack.toString()).to.equal('el1'); + + stack.push('el2'); + expect(stack.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + class MyObj { + constructor(el1, el2) { + this.el1 = el1; + this.el2 = el2; + } + + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + expect(stack.toString()).to.equal(''); + + stack.push(new MyObj(1, 2)); + expect(stack.toString()).to.equal('1|2'); + + stack.push(new MyObj(3, 4)); + expect(stack.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/js/others/balanced-symbols.spec.js b/test/js/others/balanced-symbols.spec.js new file mode 100644 index 00000000..6a2ce6e4 --- /dev/null +++ b/test/js/others/balanced-symbols.spec.js @@ -0,0 +1,41 @@ +import 'mocha'; +import { expect } from 'chai'; +import { parenthesesChecker } from '../../../src/js/others/balanced-symbols'; + +describe('Balanced Symbols', () => { + it('empty to be falsy', () => { + expect(parenthesesChecker('')).to.equal(true); + }); + + it('{ to be falsy', () => { + expect(parenthesesChecker('{')).to.equal(false); + }); + + it('} to be falsy', () => { + expect(parenthesesChecker('}')).to.equal(false); + }); + + it('11 to be falsy', () => { + expect(parenthesesChecker('11')).to.equal(false); + }); + + it('{11 to be falsy', () => { + expect(parenthesesChecker('{11')).to.equal(false); + }); + + it('{([1])} to be falsy', () => { + expect(parenthesesChecker('{([1])}')).to.equal(false); + }); + + it('{([])} to be truthy', () => { + expect(parenthesesChecker('{([])}')).to.equal(true); + }); + + it('{{([][])}()} to be truthy', () => { + expect(parenthesesChecker('{{([][])}()}')).to.equal(true); + }); + + it('[{()] to be falsy', () => { + expect(parenthesesChecker('[{()]')).to.equal(false); + }); +}); diff --git a/test/js/others/base-converter.spec.js b/test/js/others/base-converter.spec.js new file mode 100644 index 00000000..ed93a0dc --- /dev/null +++ b/test/js/others/base-converter.spec.js @@ -0,0 +1,57 @@ +import 'mocha'; +import { expect } from 'chai'; +import { baseConverter, decimalToBinary } from '../../../src/js/others/base-converter'; + +describe('Base Converter', () => { + it('decimalToBinary 1 -> 1', () => { + expect(decimalToBinary(1)).to.equal('1'); + }); + + it('decimalToBinary 2 -> 11', () => { + expect(decimalToBinary(2)).to.equal('10'); + }); + + it('decimalToBinary 233 -> 11101001', () => { + expect(decimalToBinary(233)).to.equal('11101001'); + }); + + it('decimalToBinary 10 -> 1010', () => { + expect(decimalToBinary(10)).to.equal('1010'); + }); + + it('decimalToBinary 1000 -> 1111101000', () => { + expect(decimalToBinary(1000)).to.equal('1111101000'); + }); + + it('baseConverter 100345, 2 -> 11000011111111001', () => { + expect(baseConverter(100345, 2)).to.equal('11000011111111001'); + }); + + it('baseConverter 100345, 8 -> 303771', () => { + expect(baseConverter(100345, 8)).to.equal('303771'); + }); + + it('baseConverter 100345, 16 -> 187F9', () => { + expect(baseConverter(100345, 16)).to.equal('187F9'); + }); + + it('baseConverter 100345, 7 -> 565360', () => { + expect(baseConverter(100345, 7)).to.equal('565360'); + }); + + it('baseConverter 100345, 20 -> CAH5', () => { + expect(baseConverter(100345, 20)).to.equal('CAH5'); + }); + + it('baseConverter 100345, 35 -> 2BW0', () => { + expect(baseConverter(100345, 35)).to.equal('2BW0'); + }); + + it('baseConverter 100345, 36 -> 25FD', () => { + expect(baseConverter(100345, 36)).to.equal('25FD'); + }); + + it('baseConverter 100345, 37 -> ', () => { + expect(baseConverter(100345, 37)).to.equal(''); + }); +}); diff --git a/test/js/others/factorial.spec.js b/test/js/others/factorial.spec.js new file mode 100644 index 00000000..69341a7a --- /dev/null +++ b/test/js/others/factorial.spec.js @@ -0,0 +1,25 @@ +import 'mocha'; +import { expect } from 'chai'; +import { factorialIterative, factorial } from '../../../src/js/others/factorial'; + +describe('Factorial', () => { + it('Iterative Factorial', () => { + expect(factorialIterative(-1)).to.equal(undefined); + expect(factorialIterative(0)).to.equal(1); + expect(factorialIterative(1)).to.equal(1); + expect(factorialIterative(2)).to.equal(2); + expect(factorialIterative(3)).to.equal(6); + expect(factorialIterative(4)).to.equal(24); + expect(factorialIterative(5)).to.equal(120); + }); + + it('Recursive Factorial', () => { + expect(factorial(-1)).to.equal(undefined); + expect(factorial(0)).to.equal(1); + expect(factorial(1)).to.equal(1); + expect(factorial(2)).to.equal(2); + expect(factorial(3)).to.equal(6); + expect(factorial(4)).to.equal(24); + expect(factorial(5)).to.equal(120); + }); +}); diff --git a/test/js/others/fibonacci.spec.js b/test/js/others/fibonacci.spec.js new file mode 100644 index 00000000..5eea4888 --- /dev/null +++ b/test/js/others/fibonacci.spec.js @@ -0,0 +1,36 @@ +import 'mocha'; +import { expect } from 'chai'; +import { + fibonacci, + fibonacciIterative, + fibonacciMemoization +} from '../../../src/js/others/fibonacci'; + +describe('Fibonacci', () => { + it('Fibonacci Recursive', () => { + expect(fibonacci(-1)).to.equal(0); + expect(fibonacci(0)).to.equal(0); + expect(fibonacci(1)).to.equal(1); + expect(fibonacci(2)).to.equal(1); + expect(fibonacci(3)).to.equal(2); + expect(fibonacci(4)).to.equal(3); + }); + + it('Fibonacci Iterative', () => { + expect(fibonacciIterative(-1)).to.equal(0); + expect(fibonacciIterative(0)).to.equal(0); + expect(fibonacciIterative(1)).to.equal(1); + expect(fibonacciIterative(2)).to.equal(1); + expect(fibonacciIterative(3)).to.equal(2); + expect(fibonacciIterative(4)).to.equal(3); + }); + + it('Fibonacci with Memoization', () => { + expect(fibonacciMemoization(-1)).to.equal(0); + expect(fibonacciMemoization(0)).to.equal(0); + expect(fibonacciMemoization(1)).to.equal(1); + expect(fibonacciMemoization(2)).to.equal(1); + expect(fibonacciMemoization(3)).to.equal(2); + expect(fibonacciMemoization(4)).to.equal(3); + }); +}); diff --git a/test/js/others/hanoi.spec.js b/test/js/others/hanoi.spec.js new file mode 100644 index 00000000..cca28431 --- /dev/null +++ b/test/js/others/hanoi.spec.js @@ -0,0 +1,19 @@ +import 'mocha'; +import { expect } from 'chai'; +import { hanoi, hanoiStack } from '../../../src/js/others/hanoi'; + +describe('Tower of Hanoi', () => { + it('Hanoi', () => { + for (let i = 0; i < 10; i++) { + const result = hanoi(i, 'a', 'b', 'c'); + expect(result.length).to.equal((2 ** i) - 1); + } + }); + + it('Hanoi with Stack', () => { + for (let i = 0; i < 10; i++) { + const result = hanoiStack(i); + expect(result.length).to.equal((2 ** i) - 1); + } + }); +}); diff --git a/test/js/others/hot-potato.spec.js b/test/js/others/hot-potato.spec.js new file mode 100644 index 00000000..dfbb2751 --- /dev/null +++ b/test/js/others/hot-potato.spec.js @@ -0,0 +1,14 @@ +import 'mocha'; +import { expect } from 'chai'; +import { hotPotato } from '../../../src/js/others/hot-potato'; + +describe('Hot Potato with Queue', () => { + it('Hot potato game', () => { + const names = ['John', 'Jack', 'Camila', 'Ingrid', 'Carl']; + expect(hotPotato(names, 6).winner).to.equal('Ingrid'); + expect(hotPotato(names, 7).winner).to.equal('John'); + expect(hotPotato(names, 8).winner).to.equal('Jack'); + expect(hotPotato(names, 9).winner).to.equal('Ingrid'); + expect(hotPotato(names, 10).winner).to.equal('Carl'); + }); +}); diff --git a/test/js/others/palindrome-checker.spec.js b/test/js/others/palindrome-checker.spec.js new file mode 100644 index 00000000..c5664a31 --- /dev/null +++ b/test/js/others/palindrome-checker.spec.js @@ -0,0 +1,19 @@ +import 'mocha'; +import { expect } from 'chai'; +import { palindromeChecker } from '../../../src/js/others/palindrome-checker'; + +describe('Palindrome', () => { + it('Palindrome Checker', () => { + expect(palindromeChecker('')).to.equal(false); + expect(palindromeChecker('a')).to.equal(true); + expect(palindromeChecker('aa')).to.equal(true); + expect(palindromeChecker('aba')).to.equal(true); + expect(palindromeChecker('ab')).to.equal(false); + expect(palindromeChecker('kayak')).to.equal(true); + expect(palindromeChecker('radar')).to.equal(true); + expect(palindromeChecker('level')).to.equal(true); + expect(palindromeChecker('Was it a car or a cat I saw')).to.equal(true); + expect(palindromeChecker('Step on no pets')).to.equal(true); + expect(palindromeChecker('Able was I ere I saw Elba')).to.equal(true); + }); +}); diff --git a/test/ts/algorithms/backtracking/rat-in-maze.spec.ts b/test/ts/algorithms/backtracking/rat-in-maze.spec.ts new file mode 100644 index 00000000..0a292984 --- /dev/null +++ b/test/ts/algorithms/backtracking/rat-in-maze.spec.ts @@ -0,0 +1,21 @@ +import 'mocha'; +import { expect } from 'chai'; +import { ratInAMaze } from '../../../../src/ts/index'; + +describe('Rat in a maze', () => { + it('rat in a maze solver', () => { + const maze = [ + [1, 0, 0, 0], + [1, 1, 1, 1], + [0, 0, 1, 0], + [0, 1, 1, 1] + ]; + const solution = [ + [1, 0, 0, 0], + [1, 1, 1, 0], + [0, 0, 1, 0], + [0, 0, 1, 1] + ]; + expect(ratInAMaze(maze)).to.deep.equal(solution); + }); +}); diff --git a/test/ts/algorithms/backtracking/sudoku-solver.spec.ts b/test/ts/algorithms/backtracking/sudoku-solver.spec.ts new file mode 100644 index 00000000..e747683b --- /dev/null +++ b/test/ts/algorithms/backtracking/sudoku-solver.spec.ts @@ -0,0 +1,57 @@ +import 'mocha'; +import { expect } from 'chai'; +import { sudokuSolver } from '../../../../src/ts/index'; + +describe('Sudoku Solver', () => { + it('sudoku solver', () => { + const grid = [ + [3, 0, 6, 5, 0, 8, 4, 0, 0], + [5, 2, 0, 0, 0, 0, 0, 0, 0], + [0, 8, 7, 0, 0, 0, 0, 3, 1], + [0, 0, 3, 0, 1, 0, 0, 8, 0], + [9, 0, 0, 8, 6, 3, 0, 0, 5], + [0, 5, 0, 0, 9, 0, 6, 0, 0], + [1, 3, 0, 0, 0, 0, 2, 5, 0], + [0, 0, 0, 0, 0, 0, 0, 7, 4], + [0, 0, 5, 2, 0, 6, 3, 0, 0] + ]; + const solution = [ + [3, 1, 6, 5, 7, 8, 4, 9, 2], + [5, 2, 9, 1, 3, 4, 7, 6, 8], + [4, 8, 7, 6, 2, 9, 5, 3, 1], + [2, 6, 3, 4, 1, 5, 9, 8, 7], + [9, 7, 4, 8, 6, 3, 1, 2, 5], + [8, 5, 1, 7, 9, 2, 6, 4, 3], + [1, 3, 8, 9, 4, 7, 2, 5, 6], + [6, 9, 2, 3, 5, 1, 8, 7, 4], + [7, 4, 5, 2, 8, 6, 3, 1, 9] + ]; + expect(sudokuSolver(grid)).to.deep.equal(solution); + }); + + it('sudoku solver 2', () => { + const grid = [ + [5, 3, 0, 0, 7, 0, 0, 0, 0], + [6, 0, 0, 1, 9, 5, 0, 0, 0], + [0, 9, 8, 0, 0, 0, 0, 6, 0], + [8, 0, 0, 0, 6, 0, 0, 0, 3], + [4, 0, 0, 8, 0, 3, 0, 0, 1], + [7, 0, 0, 0, 2, 0, 0, 0, 6], + [0, 6, 0, 0, 0, 0, 2, 8, 0], + [0, 0, 0, 4, 1, 9, 0, 0, 5], + [0, 0, 0, 0, 8, 0, 0, 7, 9] + ]; + const solution = [ + [5, 3, 4, 6, 7, 8, 9, 1, 2], + [6, 7, 2, 1, 9, 5, 3, 4, 8], + [1, 9, 8, 3, 4, 2, 5, 6, 7], + [8, 5, 9, 7, 6, 1, 4, 2, 3], + [4, 2, 6, 8, 5, 3, 7, 9, 1], + [7, 1, 3, 9, 2, 4, 8, 5, 6], + [9, 6, 1, 5, 3, 7, 2, 8, 4], + [2, 8, 7, 4, 1, 9, 6, 3, 5], + [3, 4, 5, 2, 8, 6, 1, 7, 9] + ]; + expect(sudokuSolver(grid)).to.deep.equal(solution); + }); +}); diff --git a/test/ts/algorithms/dynamic-programming/knapsack-recursive.spec.ts b/test/ts/algorithms/dynamic-programming/knapsack-recursive.spec.ts new file mode 100644 index 00000000..944cd655 --- /dev/null +++ b/test/ts/algorithms/dynamic-programming/knapsack-recursive.spec.ts @@ -0,0 +1,15 @@ +import 'mocha'; +import { expect } from 'chai'; +import { knapSackRecursive } from '../../../../src/ts/index'; + +describe('KnapSack Dynamic Programming - Recursive', () => { + + it('works with recursive approach', () => { + const values = [3, 4, 5]; + const weights = [2, 3, 4]; + const capacity = 5; + const n = values.length; + + expect(knapSackRecursive(capacity, weights, values, n)).to.equal(7); + }); +}); diff --git a/test/ts/algorithms/dynamic-programming/knapsack.spec.ts b/test/ts/algorithms/dynamic-programming/knapsack.spec.ts new file mode 100644 index 00000000..113f9182 --- /dev/null +++ b/test/ts/algorithms/dynamic-programming/knapsack.spec.ts @@ -0,0 +1,15 @@ +import 'mocha'; +import { expect } from 'chai'; +import { knapSack } from '../../../../src/ts/index'; + +describe('KnapSack Dynamic Programming', () => { + + it('works with DP approach', () => { + const values = [3, 4, 5]; + const weights = [2, 3, 4]; + const capacity = 5; + const n = values.length; + + expect(knapSack(capacity, weights, values, n)).to.equal(7); + }); +}); diff --git a/test/ts/algorithms/dynamic-programming/longest-common-subsequence-print.spec.ts b/test/ts/algorithms/dynamic-programming/longest-common-subsequence-print.spec.ts new file mode 100644 index 00000000..4626c593 --- /dev/null +++ b/test/ts/algorithms/dynamic-programming/longest-common-subsequence-print.spec.ts @@ -0,0 +1,13 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcsPrint } from '../../../../src/ts/index'; + +describe('LCS Dynamic Programming with print solution', () => { + + it('works with DP approach with print solution', () => { + const wordX = 'acbaed'; + const wordY = 'abcadf'; + + expect(lcsPrint(wordX, wordY)).to.equal('acad'); + }); +}); diff --git a/test/ts/algorithms/dynamic-programming/longest-common-subsequence.spec.ts b/test/ts/algorithms/dynamic-programming/longest-common-subsequence.spec.ts new file mode 100644 index 00000000..3da8abcd --- /dev/null +++ b/test/ts/algorithms/dynamic-programming/longest-common-subsequence.spec.ts @@ -0,0 +1,13 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcs } from '../../../../src/ts/index'; + +describe('LCS Dynamic Programming', () => { + + it('works with DP approach', () => { + const wordX = 'acbaed'; + const wordY = 'abcadf'; + + expect(lcs(wordX, wordY)).to.equal(4); + }); +}); diff --git a/test/ts/algorithms/dynamic-programming/matrix-chain-multiplication.spec.ts b/test/ts/algorithms/dynamic-programming/matrix-chain-multiplication.spec.ts new file mode 100644 index 00000000..09b58d2d --- /dev/null +++ b/test/ts/algorithms/dynamic-programming/matrix-chain-multiplication.spec.ts @@ -0,0 +1,12 @@ +import 'mocha'; +import { expect } from 'chai'; +import { matrixChainOrder } from '../../../../src/ts/index'; + +describe('Matrix Chain Multiplication', () => { + + it('works with DP approach', () => { + const p = [10, 100, 5, 50, 1]; + + expect(matrixChainOrder(p)).to.equal(1750); + }); +}); diff --git a/test/ts/algorithms/dynamic-programming/min-coin-change.spec.ts b/test/ts/algorithms/dynamic-programming/min-coin-change.spec.ts new file mode 100644 index 00000000..26821b06 --- /dev/null +++ b/test/ts/algorithms/dynamic-programming/min-coin-change.spec.ts @@ -0,0 +1,30 @@ +import 'mocha'; +import { expect } from 'chai'; +import { minCoinChange } from '../../../../src/ts/index'; + +describe('Dynamic Programming: Min Coin Change', () => { + + it('works with amount 0', () => { + expect(minCoinChange([1, 2, 3], 0)).to.deep.equal([]); + }); + + it('works with amount 1', () => { + expect(minCoinChange([1, 2, 3], 1)).to.deep.equal([1]); + }); + + it('works with amount 2', () => { + expect(minCoinChange([1, 2, 3], 2)).to.deep.equal([2]); + }); + + it('works with amount 3', () => { + expect(minCoinChange([1, 2, 3], 3)).to.deep.equal([3]); + }); + + it('works with amount 4', () => { + expect(minCoinChange([1, 2, 3], 4)).to.deep.equal([1, 3]); + }); + + it('works with amount 6', () => { + expect(minCoinChange([1, 2, 3], 6)).to.deep.equal([3, 3]); + }); +}); diff --git a/test/ts/algorithms/graph/breadth-first-search.spec.ts b/test/ts/algorithms/graph/breadth-first-search.spec.ts new file mode 100644 index 00000000..db5f929f --- /dev/null +++ b/test/ts/algorithms/graph/breadth-first-search.spec.ts @@ -0,0 +1,47 @@ +import 'mocha'; +import { expect } from 'chai'; +import { BFS, breadthFirstSearch, Graph } from '../../../../src/ts'; + +describe('Breadth First Search', () => { + + let count: number; + const vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + let graph: Graph; + + beforeEach(() => { + count = 0; + graph = new Graph(); + + for (let i = 0; i < vertices.length; i++) { + graph.addVertex(vertices[i]); + } + + graph.addEdge('A', 'B'); + graph.addEdge('A', 'C'); + graph.addEdge('A', 'D'); + graph.addEdge('C', 'D'); + graph.addEdge('C', 'G'); + graph.addEdge('D', 'G'); + graph.addEdge('D', 'H'); + graph.addEdge('B', 'E'); + graph.addEdge('B', 'F'); + graph.addEdge('E', 'I'); + }); + + it('breadthFirstSearch', () => { + breadthFirstSearch(graph, vertices[0], assertCallback); + }); + + function assertCallback(value: string) { + expect(value).to.equal(vertices[count]); + count++; + } + + it('sorthest path - BFS', () => { + const shortestPathA = BFS(graph, vertices[0]); + + expect(shortestPathA.distances).to.deep.equal({A: 0, B: 1, C: 1, D: 1, E: 2,  F: 2, G: 2, H: 2, I: 3}); + expect(shortestPathA.predecessors).to.deep.equal({A: null, B: 'A', C: 'A', D: 'A', E: 'B',  F: 'B', G: 'C', H: 'D', I: 'E'}); + }); + +}); diff --git a/test/ts/algorithms/graph/depth-first-search.spec.ts b/test/ts/algorithms/graph/depth-first-search.spec.ts new file mode 100644 index 00000000..763284a7 --- /dev/null +++ b/test/ts/algorithms/graph/depth-first-search.spec.ts @@ -0,0 +1,58 @@ +import 'mocha'; +import { expect } from 'chai'; +import { DFS, depthFirstSearch, Graph } from '../../../../src/ts/index'; + +describe('Depth First Search', () => { + let count: number; + const vertices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']; + const dfsCallBack = ['A', 'B', 'E', 'I', 'F', 'C', 'D', 'G', 'H']; + let graph: Graph; + + beforeEach(() => { + count = 0; + graph = new Graph(true); + }); + + it('depthFirstSearch', () => { + for (let i = 0; i < vertices.length; i++) { + graph.addVertex(vertices[i]); + } + + graph.addEdge('A', 'B'); + graph.addEdge('A', 'C'); + graph.addEdge('A', 'D'); + graph.addEdge('C', 'D'); + graph.addEdge('C', 'G'); + graph.addEdge('D', 'G'); + graph.addEdge('D', 'H'); + graph.addEdge('B', 'E'); + graph.addEdge('B', 'F'); + graph.addEdge('E', 'I'); + + depthFirstSearch(graph, assertCallback); + }); + + function assertCallback(value: string) { + expect(value).to.equal(dfsCallBack[count]); + count++; + } + + it('topological sort - DFS', () => { + const myVertices = ['A', 'B', 'C', 'D', 'E', 'F']; + for (let i = 0; i < myVertices.length; i++) { + graph.addVertex(myVertices[i]); + } + graph.addEdge('A', 'C'); + graph.addEdge('A', 'D'); + graph.addEdge('B', 'D'); + graph.addEdge('B', 'E'); + graph.addEdge('C', 'F'); + graph.addEdge('F', 'E'); + + const result = DFS(graph); + + expect(result.discovery).to.deep.equal({A: 1, B: 11, C: 2, D: 8, E: 4, F: 3}); + expect(result.finished).to.deep.equal({A: 10, B: 12, C: 7, D: 9, E: 5, F: 6}); + expect(result.predecessors).to.deep.equal({A: null, B: null, C: 'A', D: 'A', E: 'F', F: 'C'}); + }); +}); diff --git a/test/ts/algorithms/graph/dijkstra.spec.ts b/test/ts/algorithms/graph/dijkstra.spec.ts new file mode 100644 index 00000000..05b2e2f9 --- /dev/null +++ b/test/ts/algorithms/graph/dijkstra.spec.ts @@ -0,0 +1,21 @@ +import 'mocha'; +import { expect } from 'chai'; +import { dijkstra } from '../../../../src/ts/index'; + +describe('Dijkstra\'s Algorithm - Shortest Path', () => { + + it('Shortest Path', () => { + const graph = [ + [0, 2, 4, 0, 0, 0], + [0, 0, 2, 4, 2, 0], + [0, 0, 0, 0, 3, 0], + [0, 0, 0, 0, 0, 2], + [0, 0, 0, 3, 0, 2], + [0, 0, 0, 0, 0, 0] + ]; + + expect(dijkstra(graph, 0)).to.deep.equal([0, 2, 4, 6, 4, 6]); + + }); + +}); diff --git a/test/ts/algorithms/graph/floyd-warshall.spec.ts b/test/ts/algorithms/graph/floyd-warshall.spec.ts new file mode 100644 index 00000000..cf0adae2 --- /dev/null +++ b/test/ts/algorithms/graph/floyd-warshall.spec.ts @@ -0,0 +1,26 @@ +import 'mocha'; +import { expect } from 'chai'; +import { floydWarshall } from '../../../../src/ts/index'; + +describe('Floyd-Warshall Algorithm - All-Pairs Shortest Path', () => { + it('All-Pairs Shortest Path', () => { + const INF = Infinity; + const graph = [ + [INF, 2, 4, INF, INF, INF], + [INF, INF, 2, 4, 2, INF], + [INF, INF, INF, INF, 3, INF], + [INF, INF, INF, INF, INF, 2], + [INF, INF, INF, 3, INF, 2], + [INF, INF, INF, INF, INF, INF] + ]; + + expect(floydWarshall(graph)).to.deep.equal([ + [0, 2, 4, 6, 4, 6], + [INF, 0, 2, 4, 2, 4], + [INF, INF, 0, 6, 3, 5], + [INF, INF, INF, 0, INF, 2], + [INF, INF, INF, 3, 0, 2], + [INF, INF, INF, INF, INF, 0] + ]); + }); +}); diff --git a/test/ts/algorithms/graph/kruskal.spec.ts b/test/ts/algorithms/graph/kruskal.spec.ts new file mode 100644 index 00000000..838c643e --- /dev/null +++ b/test/ts/algorithms/graph/kruskal.spec.ts @@ -0,0 +1,18 @@ +import 'mocha'; +import { expect } from 'chai'; +import { kruskal } from '../../../../src/ts/index'; + +describe('Kruskal Algorithm - Minimum Spanning Tree', () => { + it('Minimum Spanning Tree', () => { + const graph = [ + [0, 2, 4, 0, 0, 0], + [2, 0, 2, 4, 2, 0], + [4, 2, 0, 0, 3, 0], + [0, 4, 0, 0, 3, 2], + [0, 2, 3, 3, 0, 2], + [0, 0, 0, 2, 2, 0] + ]; + + expect(kruskal(graph)).to.deep.equal([ , 0, 1, 1, 1, 3]); + }); +}); diff --git a/test/ts/algorithms/graph/prim.spec.ts b/test/ts/algorithms/graph/prim.spec.ts new file mode 100644 index 00000000..18224d71 --- /dev/null +++ b/test/ts/algorithms/graph/prim.spec.ts @@ -0,0 +1,18 @@ +import 'mocha'; +import { expect } from 'chai'; +import { prim } from '../../../../src/ts/index'; + +describe('Prim\'s Algorithm - Minimum Spanning Tree', () => { + it('Minimum Spanning Tree', () => { + const graph = [ + [0, 2, 4, 0, 0, 0], + [2, 0, 2, 4, 2, 0], + [4, 2, 0, 0, 3, 0], + [0, 4, 0, 0, 3, 2], + [0, 2, 3, 3, 0, 2], + [0, 0, 0, 2, 2, 0] + ]; + + expect(prim(graph)).to.deep.equal([-1, 0, 1, 5, 1, 4]); + }); +}); diff --git a/test/ts/algorithms/greedy/knapsack.spec.ts b/test/ts/algorithms/greedy/knapsack.spec.ts new file mode 100644 index 00000000..de73ff47 --- /dev/null +++ b/test/ts/algorithms/greedy/knapsack.spec.ts @@ -0,0 +1,14 @@ +import 'mocha'; +import { expect } from 'chai'; +import { knapSackGreedy } from '../../../../src/ts/index'; + +describe('KnapSack Greedy', () => { + + it('works with greedy approach', () => { + const values = [3, 4, 5]; + const weights = [2, 3, 4]; + const capacity = 5; + + expect(knapSackGreedy(capacity, weights, values)).to.equal(7); + }); +}); diff --git a/test/ts/algorithms/greedy/longest-common-subsequence.spec.ts b/test/ts/algorithms/greedy/longest-common-subsequence.spec.ts new file mode 100644 index 00000000..82d4000a --- /dev/null +++ b/test/ts/algorithms/greedy/longest-common-subsequence.spec.ts @@ -0,0 +1,13 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcsRecursive } from '../../../../src/ts/index'; + +describe('LCS Greedy', () => { + + it('works with Greedy approach', () => { + const wordX = 'acbaed'; + const wordY = 'abcadf'; + + expect(lcsRecursive(wordX, wordY)).to.equal(4); + }); +}); diff --git a/test/ts/algorithms/greedy/matrix-chain-multiplication.spec.ts b/test/ts/algorithms/greedy/matrix-chain-multiplication.spec.ts new file mode 100644 index 00000000..d6655752 --- /dev/null +++ b/test/ts/algorithms/greedy/matrix-chain-multiplication.spec.ts @@ -0,0 +1,12 @@ +import 'mocha'; +import { expect } from 'chai'; +import { matrixChainOrderGreedy } from '../../../../src/ts/index'; + +describe('Matrix Chain Multiplication', () => { + + it('works with DP approach', () => { + const p = [10, 100, 5, 50, 1]; + + expect(matrixChainOrderGreedy(p)).to.equal(1750); + }); +}); diff --git a/test/ts/algorithms/greedy/min-coin-change.spec.ts b/test/ts/algorithms/greedy/min-coin-change.spec.ts new file mode 100644 index 00000000..946d19ff --- /dev/null +++ b/test/ts/algorithms/greedy/min-coin-change.spec.ts @@ -0,0 +1,12 @@ +import 'mocha'; +import { expect } from 'chai'; +import { minCoinChangeGreedy } from '../../../../src/ts/index'; + +describe('Min Coin Change Greedy', () => { + + it('works with greedy approach', () => { + expect(minCoinChangeGreedy([1, 5, 10], 15)).to.deep.equal([10, 5]); + expect(minCoinChangeGreedy([1, 3, 4], 6)).to.deep.equal([4, 1, 1]); + }); + +}); diff --git a/test/ts/algorithms/math/find-divisors.spec.ts b/test/ts/algorithms/math/find-divisors.spec.ts new file mode 100644 index 00000000..b4223378 --- /dev/null +++ b/test/ts/algorithms/math/find-divisors.spec.ts @@ -0,0 +1,17 @@ +import 'mocha'; +import { expect } from 'chai'; +import { findDivisors } from '../../../../src/ts/index'; + +describe('Find Divisors', () => { + + it('returns the divisors of the number', () => { + + expect(findDivisors(-1)).to.deep.equal([]); + expect(findDivisors(0)).to.deep.equal([]); + expect(findDivisors(1)).to.deep.equal([1]); + expect(findDivisors(2)).to.deep.equal([1, 2]); + expect(findDivisors(3)).to.deep.equal([1, 3]); + expect(findDivisors(4)).to.deep.equal([1, 2, 4]); + expect(findDivisors(100)).to.deep.equal([1, 2, 4, 5, 10, 20, 25, 50, 100 ]); + }); +}); diff --git a/test/ts/algorithms/math/gcd.spec.ts b/test/ts/algorithms/math/gcd.spec.ts new file mode 100644 index 00000000..fd565a33 --- /dev/null +++ b/test/ts/algorithms/math/gcd.spec.ts @@ -0,0 +1,16 @@ +import 'mocha'; +import { expect } from 'chai'; +import { gcd } from '../../../../src/ts/index'; + +describe('GCD', () => { + + it('returns the gcd between two numbers', () => { + + expect(gcd(1, 0)).to.equal(0); + expect(gcd(1, 1)).to.equal(1); + expect(gcd(2, 2)).to.equal(2); + expect(gcd(2, 4)).to.equal(2); + expect(gcd(2, 3)).to.equal(1); + expect(gcd(10, 1000)).to.equal(10); + }); +}); diff --git a/test/ts/algorithms/math/greatest-difference.spec.ts b/test/ts/algorithms/math/greatest-difference.spec.ts new file mode 100644 index 00000000..889e4ef6 --- /dev/null +++ b/test/ts/algorithms/math/greatest-difference.spec.ts @@ -0,0 +1,14 @@ +import 'mocha'; +import { expect } from 'chai'; +import { greatestDifference } from '../../../../src/ts/index'; + +describe('Greatest Difference', () => { + + it('returns the gcd between two numbers', () => { + + expect(greatestDifference([5, 6, 7, 2, 10])).to.equal(8); + expect(greatestDifference([1, 2, 4])).to.equal(3); + expect(greatestDifference([1, 3])).to.equal(2); + + }); +}); diff --git a/test/ts/algorithms/math/lcm.spec.ts b/test/ts/algorithms/math/lcm.spec.ts new file mode 100644 index 00000000..2262161c --- /dev/null +++ b/test/ts/algorithms/math/lcm.spec.ts @@ -0,0 +1,16 @@ +import 'mocha'; +import { expect } from 'chai'; +import { lcm } from '../../../../src/ts/index'; + +describe('LCM', () => { + + it('returns the lcm between two numbers', () => { + + expect(lcm(0, 0)).to.equal(0); + expect(lcm(1, 1)).to.equal(1); + expect(lcm(1, 2)).to.equal(2); + expect(lcm(2, 4)).to.equal(4); + expect(lcm(2, 3)).to.equal(6); + + }); +}); diff --git a/test/ts/algorithms/math/primality-test.spec.ts b/test/ts/algorithms/math/primality-test.spec.ts new file mode 100644 index 00000000..36680623 --- /dev/null +++ b/test/ts/algorithms/math/primality-test.spec.ts @@ -0,0 +1,30 @@ +import 'mocha'; +import { expect } from 'chai'; +import { isPrime, testPrime, isPrime2 } from '../../../../src/ts/index'; + +describe('Primality Tests', () => { + + it('returns if the number is prime or not - isPrime', () => { + testIsPrime(isPrime); + }); + + it('returns if the number is prime or not - testPrime', () => { + testIsPrime(testPrime); + }); + + it('returns if the number is prime or not - isPrime2', () => { + testIsPrime(isPrime2); + }); + + function testIsPrime(primeFunction: Function) { + expect(primeFunction(-1)).to.equal(false); + expect(primeFunction(0)).to.equal(false); + expect(primeFunction(1)).to.equal(false); + expect(primeFunction(2)).to.equal(true); + expect(primeFunction(3)).to.equal(true); + expect(primeFunction(4)).to.equal(false); + expect(primeFunction(5)).to.equal(true); + expect(primeFunction(10)).to.equal(false); + expect(primeFunction(113)).to.equal(true); + } +}); diff --git a/test/ts/algorithms/math/sieve-eratosthenes.spec.ts b/test/ts/algorithms/math/sieve-eratosthenes.spec.ts new file mode 100644 index 00000000..1cd31c2d --- /dev/null +++ b/test/ts/algorithms/math/sieve-eratosthenes.spec.ts @@ -0,0 +1,17 @@ +import 'mocha'; +import { expect } from 'chai'; +import { sieveOfEratosthenes } from '../../../../src/ts/index'; + +describe('Sieve Of Eratosthene', () => { + + it('returns the prime numbers', () => { + + expect(sieveOfEratosthenes(0)).to.deep.equal([]); + expect(sieveOfEratosthenes(1)).to.deep.equal([]); + expect(sieveOfEratosthenes(2)).to.deep.equal([2]); + expect(sieveOfEratosthenes(3)).to.deep.equal([2, 3]); + expect(sieveOfEratosthenes(4)).to.deep.equal([2, 3]); + expect(sieveOfEratosthenes(5)).to.deep.equal([2, 3, 5]); + + }); +}); diff --git a/test/ts/algorithms/search/binary-search-recursive.spec.ts b/test/ts/algorithms/search/binary-search-recursive.spec.ts new file mode 100644 index 00000000..b06ce773 --- /dev/null +++ b/test/ts/algorithms/search/binary-search-recursive.spec.ts @@ -0,0 +1,5 @@ +import { binarySearchRecursive } from '../../../../src/ts/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(binarySearchRecursive, 'Binary Search Recursive'); + diff --git a/test/ts/algorithms/search/binary-search.spec.ts b/test/ts/algorithms/search/binary-search.spec.ts new file mode 100644 index 00000000..f62d0e96 --- /dev/null +++ b/test/ts/algorithms/search/binary-search.spec.ts @@ -0,0 +1,5 @@ +import { binarySearch } from '../../../../src/ts/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(binarySearch, 'Binary Search'); + diff --git a/test/ts/algorithms/search/interpolation-search.spec.ts b/test/ts/algorithms/search/interpolation-search.spec.ts new file mode 100644 index 00000000..287351f2 --- /dev/null +++ b/test/ts/algorithms/search/interpolation-search.spec.ts @@ -0,0 +1,5 @@ +import { interpolationSearch } from '../../../../src/ts/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(interpolationSearch, 'Interpolation Search', { customEquals: false }); + diff --git a/test/ts/algorithms/search/min-max-search.spec.ts b/test/ts/algorithms/search/min-max-search.spec.ts new file mode 100644 index 00000000..d0dd76c3 --- /dev/null +++ b/test/ts/algorithms/search/min-max-search.spec.ts @@ -0,0 +1,32 @@ +import 'mocha'; +import { expect } from 'chai'; +import { findMinValue, findMaxValue } from '../../../../src/ts/index'; + +describe('Min and Max Values Search', () => { + + const SIZE = 10; + + function createSortedArray() { + const array: number[] = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('min value - works with empty arrays', () => { + expect(findMinValue([])).to.equal(undefined); + }); + + it('max value - works with empty arrays', () => { + expect(findMaxValue([])).to.equal(undefined); + }); + + it('min value', () => { + expect(findMinValue(createSortedArray())).to.equal(1); + }); + + it('max value', () => { + expect(findMaxValue(createSortedArray())).to.equal(SIZE); + }); +}); diff --git a/test/ts/algorithms/search/search-algorithms-tests.ts b/test/ts/algorithms/search/search-algorithms-tests.ts new file mode 100644 index 00000000..dd590f5d --- /dev/null +++ b/test/ts/algorithms/search/search-algorithms-tests.ts @@ -0,0 +1,57 @@ +import 'mocha'; +import { expect } from 'chai'; +import { IEqualsFunction } from '../../../../src/ts/util'; + +interface CustomObject { + key: number; +} + +const customEquals: IEqualsFunction = (a: CustomObject, b: CustomObject) => + a.key === b.key; + +export function testSearchAlgorithm( + searchAlgorithm: Function, + algorithmName: string, + config = { customEquals: true } +) { + describe(algorithmName, () => { + const SIZE = 10; + + function createSortedArray() { + const array: number[] = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('works with empty arrays', () => { + expect(searchAlgorithm([], 1)).to.equal(-1); + }); + + it('finds value at the first position', () => { + const array = createSortedArray(); + expect(searchAlgorithm(array, 1)).to.equal(0); + }); + + it('finds value at the last position', () => { + const array = createSortedArray(); + expect(searchAlgorithm(array, SIZE)).to.equal(SIZE - 1); + }); + + it('finds value at different positions', () => { + const array = createSortedArray(); + + for (let value = 1; value <= SIZE; value++) { + expect(searchAlgorithm(array, value)).to.equal(value - 1); + } + }); + + if (config.customEquals) { + it('finds value with custom equals function', () => { + const array = [{ key: 1 }, { key: 2 }, { key: 3 }]; + expect(searchAlgorithm(array, { key: 2 }, customEquals)).to.equal(1); + }); + } + }); +} diff --git a/test/ts/algorithms/search/sequential-search.spec.ts b/test/ts/algorithms/search/sequential-search.spec.ts new file mode 100644 index 00000000..94ddf885 --- /dev/null +++ b/test/ts/algorithms/search/sequential-search.spec.ts @@ -0,0 +1,5 @@ +import { sequentialSearch } from '../../../../src/ts/index'; +import { testSearchAlgorithm } from './search-algorithms-tests'; + +testSearchAlgorithm(sequentialSearch, 'Sequential Search'); + diff --git "a/test/ts/algorithms/shuffle/fisher\342\200\223yates.spec.ts" "b/test/ts/algorithms/shuffle/fisher\342\200\223yates.spec.ts" new file mode 100644 index 00000000..da450f41 --- /dev/null +++ "b/test/ts/algorithms/shuffle/fisher\342\200\223yates.spec.ts" @@ -0,0 +1,33 @@ +import 'mocha'; +import { expect } from 'chai'; +import { shuffle } from '../../../../src/ts/index'; + +describe('Fisher-Yates Suffle', () => { + + const SIZE = 100; + + function createSortedArray() { + const array: number[] = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('works with empty arrays', () => { + expect(shuffle([])).to.deep.equal([]); + }); + + it('works with arrays with a single value', () => { + const array = [1]; + expect(shuffle(array)).to.deep.equal(array); + }); + + it('works with sorted arrays', () => { + let array = createSortedArray(); + const sortedArray = createSortedArray(); + array = shuffle(array); + expect(array).to.not.deep.equal(sortedArray); + }); + +}); diff --git a/test/ts/algorithms/sorting/bubble-sort-improved.spec.ts b/test/ts/algorithms/sorting/bubble-sort-improved.spec.ts new file mode 100644 index 00000000..7686a5fd --- /dev/null +++ b/test/ts/algorithms/sorting/bubble-sort-improved.spec.ts @@ -0,0 +1,5 @@ +import { modifiedBubbleSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(modifiedBubbleSort, 'Bubble Sort - Improved'); + diff --git a/test/ts/algorithms/sorting/bubble-sort.spec.ts b/test/ts/algorithms/sorting/bubble-sort.spec.ts new file mode 100644 index 00000000..2804fe9c --- /dev/null +++ b/test/ts/algorithms/sorting/bubble-sort.spec.ts @@ -0,0 +1,5 @@ +import { bubbleSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(bubbleSort, 'Bubble Sort'); + diff --git a/test/ts/algorithms/sorting/bucket-sort.spec.ts b/test/ts/algorithms/sorting/bucket-sort.spec.ts new file mode 100644 index 00000000..1a4ec458 --- /dev/null +++ b/test/ts/algorithms/sorting/bucket-sort.spec.ts @@ -0,0 +1,4 @@ +import { bucketSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(bucketSort, 'Bucket Sort', {reverseCompare: false}); diff --git a/test/ts/algorithms/sorting/counting-sort.spec.ts b/test/ts/algorithms/sorting/counting-sort.spec.ts new file mode 100644 index 00000000..c3fee9a5 --- /dev/null +++ b/test/ts/algorithms/sorting/counting-sort.spec.ts @@ -0,0 +1,4 @@ +import { countingSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(countingSort, 'Counting Sort', {reverseCompare: false}); diff --git a/test/ts/algorithms/sorting/heap-sort.spec.ts b/test/ts/algorithms/sorting/heap-sort.spec.ts new file mode 100644 index 00000000..b0b95da9 --- /dev/null +++ b/test/ts/algorithms/sorting/heap-sort.spec.ts @@ -0,0 +1,5 @@ +import { heapSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(heapSort, 'Heap Sort'); + diff --git a/test/ts/algorithms/sorting/insertion-sort.spec.ts b/test/ts/algorithms/sorting/insertion-sort.spec.ts new file mode 100644 index 00000000..86beb941 --- /dev/null +++ b/test/ts/algorithms/sorting/insertion-sort.spec.ts @@ -0,0 +1,5 @@ +import { insertionSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(insertionSort, 'Insertion Sort'); + diff --git a/test/ts/algorithms/sorting/merge-sort.spec.ts b/test/ts/algorithms/sorting/merge-sort.spec.ts new file mode 100644 index 00000000..cf4a7418 --- /dev/null +++ b/test/ts/algorithms/sorting/merge-sort.spec.ts @@ -0,0 +1,5 @@ +import { mergeSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(mergeSort, 'Merge Sort'); + diff --git a/test/ts/algorithms/sorting/quicksort.spec.ts b/test/ts/algorithms/sorting/quicksort.spec.ts new file mode 100644 index 00000000..348c58f4 --- /dev/null +++ b/test/ts/algorithms/sorting/quicksort.spec.ts @@ -0,0 +1,5 @@ +import { quickSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(quickSort, 'Quick Sort'); + diff --git a/test/ts/algorithms/sorting/radix-sort.spec.ts b/test/ts/algorithms/sorting/radix-sort.spec.ts new file mode 100644 index 00000000..36f909ce --- /dev/null +++ b/test/ts/algorithms/sorting/radix-sort.spec.ts @@ -0,0 +1,5 @@ +import { radixSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(radixSort, 'Radix Sort', {reverseCompare: false}); + diff --git a/test/ts/algorithms/sorting/selection-sort.spec.ts b/test/ts/algorithms/sorting/selection-sort.spec.ts new file mode 100644 index 00000000..a1359074 --- /dev/null +++ b/test/ts/algorithms/sorting/selection-sort.spec.ts @@ -0,0 +1,5 @@ +import { selectionSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(selectionSort, 'Selection Sort'); + diff --git a/test/ts/algorithms/sorting/shell-sort.spec.ts b/test/ts/algorithms/sorting/shell-sort.spec.ts new file mode 100644 index 00000000..4683a70c --- /dev/null +++ b/test/ts/algorithms/sorting/shell-sort.spec.ts @@ -0,0 +1,5 @@ +import { shellSort } from '../../../../src/ts/index'; +import { testSortAlgorithm } from './sort-algorithm-tests'; + +testSortAlgorithm(shellSort, 'Shell Sort'); + diff --git a/test/ts/algorithms/sorting/sort-algorithm-tests.ts b/test/ts/algorithms/sorting/sort-algorithm-tests.ts new file mode 100644 index 00000000..c1bacf3d --- /dev/null +++ b/test/ts/algorithms/sorting/sort-algorithm-tests.ts @@ -0,0 +1,73 @@ +import 'mocha'; +import { expect } from 'chai'; +import { Compare } from '../../../../src/ts/util'; + +export function testSortAlgorithm( + sortAlgorithm: Function, + algorithmName: string, + config = { reverseCompare: true } +) { + describe(algorithmName, () => { + const SIZE = 100; + + function createNonSortedArray() { + const array: number[] = []; + for (let i = SIZE; i > 0; i--) { + array.push(i); + } + return array; + } + + function createSortedArray() { + const array: number[] = []; + for (let i = 1; i <= SIZE; i++) { + array.push(i); + } + return array; + } + + it('works with empty arrays', () => { + expect(sortAlgorithm([])).to.deep.equal([]); + }); + + it('works with sorted arrays', () => { + let array = createSortedArray(); + const sortedArray = createSortedArray(); + array = sortAlgorithm(array); + expect(array).to.deep.equal(sortedArray); + }); + + it('works with non-sorted arrays', () => { + let array = createNonSortedArray(); + const sortedArray = createSortedArray(); + array = sortAlgorithm(array); + + expect(array).to.deep.equal(sortedArray); + + for (let i = 0; i < array.length - 1; i++) { + expect(array[i] <= array[i + 1]).to.equal(true); + } + }); + + function reverseCompare(a: T, b: T): number { + if (a === b) { + return 0; + } + return a < b ? Compare.BIGGER_THAN : Compare.LESS_THAN; + } + + if (config.reverseCompare) { + it('works with reverse comparator - descending order', () => { + let array = createSortedArray(); + const sortedArray = createNonSortedArray(); + array = sortAlgorithm(array, reverseCompare); + + expect(array).to.deep.equal(sortedArray); + + for (let i = 0; i < array.length - 1; i++) { + expect(array[i] >= array[i + 1]).to.equal(true); + } + }); + } + }); +} diff --git a/test/ts/data-structures/avl-tree.spec.ts b/test/ts/data-structures/avl-tree.spec.ts new file mode 100644 index 00000000..95562b95 --- /dev/null +++ b/test/ts/data-structures/avl-tree.spec.ts @@ -0,0 +1,32 @@ +import 'mocha'; +import { expect } from 'chai'; +import { AVLTree } from '../../../src/ts/index'; + +describe('AVLTree', () => { + let tree: AVLTree; + + beforeEach(() => { + tree = new AVLTree(); + }); + + it('starts empty', () => { + expect(tree.getRoot()).to.equal(undefined); + }); + + it('inserts elements in the AVLTree', () => { + expect(tree.getRoot()).to.equal(undefined); + + tree.insert(1); + tree.insert(2); + tree.insert(3); + tree.insert(4); + tree.insert(5); + tree.insert(6); + tree.insert(7); + tree.insert(14); + tree.insert(15); + tree.insert(13); + tree.insert(12); + tree.insert(11); + }); +}); diff --git a/test/ts/data-structures/binary-search-tree.spec.ts b/test/ts/data-structures/binary-search-tree.spec.ts new file mode 100644 index 00000000..419f8e10 --- /dev/null +++ b/test/ts/data-structures/binary-search-tree.spec.ts @@ -0,0 +1,109 @@ +import 'mocha'; +import { expect } from 'chai'; +import { BinarySearchTree } from '../../../src/ts/index'; + +describe('BinarySearchTree', () => { + let tree: BinarySearchTree; + + beforeEach(() => { + tree = new BinarySearchTree(); + }); + + it('starts empty', () => { + expect(tree.getRoot()).to.equal(undefined); + }); + + function assertNode(node: any, key: number, left: number, right: number) { + + if (key != null) { + expect(node.key).to.equal(key); + } else { + expect(node).to.equal(key); + return; + } + + if (left != null) { + expect(node.left.key).to.equal(left); + } else { + expect(node.left).to.equal(left); + } + + if (right != null) { + expect(node.right.key).to.equal(right); + } else { + expect(node.right).to.equal(right); + } + } + + it('inserts elements in the BST', () => { + expect(tree.getRoot()).to.equal(undefined); + + tree.insert(11); + tree.insert(7); + tree.insert(15); + tree.insert(5); + tree.insert(3); + tree.insert(9); + tree.insert(8); + tree.insert(10); + tree.insert(13); + tree.insert(12); + tree.insert(14); + tree.insert(20); + tree.insert(18); + tree.insert(25); + + let node = tree.getRoot(); + assertNode(node, 11, 7, 15); + + node = node.left; + assertNode(node, 7, 5, 9); + + node = node.left; + assertNode(node, 5, 3, undefined); + + node = node.left; + assertNode(node, 3, undefined, undefined); + + node = tree.getRoot().left.left.right; + assertNode(node, undefined, undefined, undefined); + + node = tree.getRoot().left.right; + assertNode(node, 9, 8, 10); + + node = node.left; + assertNode(node, 8, undefined, undefined); + + node = tree.getRoot().left.right.right; + assertNode(node, 10, undefined, undefined); + + node = tree.getRoot().right; + assertNode(node, 15, 13, 20); + + node = node.left; + assertNode(node, 13, 12, 14); + + node = node.left; + assertNode(node, 12, undefined, undefined); + + node = tree.getRoot().right.left.right; + assertNode(node, 14, undefined, undefined); + + node = tree.getRoot().right.right; + assertNode(node, 20, 18, 25); + + node = node.left; + assertNode(node, 18, undefined, undefined); + + node = tree.getRoot().right.right.right; + assertNode(node, 25, undefined, undefined); + }); + + it('verifies if element exists', () => { + expect(tree.getRoot()).to.equal(undefined); + }); + + it('removes a leaf', () => { + expect(tree.getRoot()).to.equal(undefined); + }); +}); diff --git a/test/ts/data-structures/circular-linked-list.spec.ts b/test/ts/data-structures/circular-linked-list.spec.ts new file mode 100644 index 00000000..78312614 --- /dev/null +++ b/test/ts/data-structures/circular-linked-list.spec.ts @@ -0,0 +1,342 @@ +import 'mocha'; +import { expect } from 'chai'; +import { CircularLinkedList } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('CircularLinkedList', () => { + let list: CircularLinkedList; + let min: number; + let max: number; + + beforeEach(() => { + list = new CircularLinkedList(); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = min; i <= max; i++) { + list.push(i); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max && current; i++) { + expect(current).to.not.be.an('undefined'); + if (current) { + // TS strictNullChecks + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + // TS strictNullChecks + expect(current.next.element).to.equal(i + 1); + } + } else { + // circular list + expect(current.next).to.not.be.an('undefined'); + expect(current.next).to.equal(list.getHead()); + if (current.next) { + expect(current.next.element).to.equal(min); + } + } + current = current.next; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max, 0)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + expect(list.insert(1, 1)).to.equal(false); + }); + + it('inserts elements invalid position not empty list', () => { + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(false); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i , i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + const minIndex = min; + for (let i = minIndex; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + min++; + verifyList(); + } + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(min); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(max); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(max); + expect(current.next).to.not.be.an('undefined'); + expect(current.next).to.equal(list.getHead()); + if (current.next) { + expect(current.next.element).to.equal(min); + } + } + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new CircularLinkedList(); + ds.push('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new CircularLinkedList(); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/deque.spec.ts b/test/ts/data-structures/deque.spec.ts new file mode 100644 index 00000000..7dcb4c8a --- /dev/null +++ b/test/ts/data-structures/deque.spec.ts @@ -0,0 +1,204 @@ +import 'mocha'; +import { expect } from 'chai'; +import Deque from '../../../src/ts/data-structures/deque'; + +describe('Deque', () => { + let deque: Deque; + + beforeEach(() => { + deque = new Deque(); + }); + + it('starts empty', () => { + expect(deque.size()).to.equal(0); + expect(deque.isEmpty()).to.equal(true); + }); + + it('add elements in the back', () => { + deque.addBack(1); + expect(deque.size()).to.equal(1); + + deque.addBack(2); + expect(deque.size()).to.equal(2); + + deque.addBack(3); + expect(deque.size()).to.equal(3); + }); + + it('add elements in the front', () => { + deque.addFront(1); + expect(deque.size()).to.equal(1); + + deque.addFront(2); + expect(deque.size()).to.equal(2); + + deque.addFront(3); + expect(deque.size()).to.equal(3); + + deque.removeFront(); + deque.addFront(4); + expect(deque.size()).to.equal(3); + }); + + it('remove elements from the back', () => { + deque.addBack(1); + deque.addBack(2); + deque.addBack(3); + deque.addFront(0); + + expect(deque.removeBack()).to.equal(3); + expect(deque.removeBack()).to.equal(2); + expect(deque.removeBack()).to.equal(1); + expect(deque.removeBack()).to.equal(0); + expect(deque.removeBack()).to.equal(undefined); + }); + + it('remove elements from the front', () => { + deque.addFront(1); + deque.addBack(2); + deque.addBack(3); + deque.addFront(0); + deque.addFront(-1); + deque.addFront(-2); + + expect(deque.removeFront()).to.equal(-2); + expect(deque.removeFront()).to.equal(-1); + expect(deque.removeFront()).to.equal(0); + expect(deque.removeFront()).to.equal(1); + expect(deque.removeFront()).to.equal(2); + expect(deque.removeFront()).to.equal(3); + expect(deque.removeFront()).to.equal(undefined); + }); + + it('allows to peek at the front element in the deque without removing it', () => { + expect(deque.peekFront()).to.equal(undefined); + + deque.addFront(1); + expect(deque.peekFront()).to.equal(1); + deque.addBack(2); + expect(deque.peekFront()).to.equal(1); + deque.addBack(3); + expect(deque.peekFront()).to.equal(1); + deque.addFront(0); + expect(deque.peekFront()).to.equal(0); + deque.addFront(-1); + expect(deque.peekFront()).to.equal(-1); + deque.addFront(-2); + expect(deque.peekFront()).to.equal(-2); + }); + + it('allows to peek at the last element in the deque without removing it', () => { + expect(deque.peekBack()).to.equal(undefined); + + deque.addFront(1); + expect(deque.peekBack()).to.equal(1); + deque.addBack(2); + expect(deque.peekBack()).to.equal(2); + deque.addBack(3); + expect(deque.peekBack()).to.equal(3); + deque.addFront(0); + expect(deque.peekBack()).to.equal(3); + deque.addFront(-1); + expect(deque.peekBack()).to.equal(3); + deque.addFront(-2); + expect(deque.peekBack()).to.equal(3); + }); + + it('returns the correct size', () => { + expect(deque.size()).to.equal(0); + + deque.addFront(1); + expect(deque.size()).to.equal(1); + deque.addBack(2); + expect(deque.size()).to.equal(2); + deque.addBack(3); + expect(deque.size()).to.equal(3); + deque.addFront(0); + expect(deque.size()).to.equal(4); + deque.addFront(-1); + expect(deque.size()).to.equal(5); + deque.addFront(-2); + expect(deque.size()).to.equal(6); + + deque.clear(); + expect(deque.size()).to.equal(0); + + deque.addFront(1); + deque.addBack(2); + expect(deque.size()).to.equal(2); + + deque.removeFront(); + deque.removeBack(); + expect(deque.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(deque.isEmpty()).to.equal(true); + + deque.addFront(1); + expect(deque.isEmpty()).to.equal(false); + deque.addBack(2); + expect(deque.isEmpty()).to.equal(false); + + deque.clear(); + expect(deque.isEmpty()).to.equal(true); + + deque.addFront(1); + deque.addBack(2); + expect(deque.isEmpty()).to.equal(false); + + deque.removeFront(); + expect(deque.isEmpty()).to.equal(false); + deque.removeBack(); + expect(deque.isEmpty()).to.equal(true); + }); + + it('clears the queue', () => { + deque.clear(); + expect(deque.isEmpty()).to.equal(true); + + deque.addFront(1); + deque.addBack(2); + expect(deque.isEmpty()).to.equal(false); + + deque.clear(); + expect(deque.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(deque.toString()).to.equal(''); + + deque.addFront(1); + expect(deque.toString()).to.equal('1'); + + deque.addBack(2); + expect(deque.toString()).to.equal('1,2'); + + deque.clear(); + expect(deque.toString()).to.equal(''); + + const queueString = new Deque(); + queueString.addFront('el1'); + expect(queueString.toString()).to.equal('el1'); + + queueString.addBack('el2'); + expect(queueString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + class MyObj { + constructor(public el1: any, public el2: any) {} + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + const dequeMyObj = new Deque(); + expect(dequeMyObj.toString()).to.equal(''); + + dequeMyObj.addFront(new MyObj(1, 2)); + expect(dequeMyObj.toString()).to.equal('1|2'); + + dequeMyObj.addBack(new MyObj(3, 4)); + expect(dequeMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/dictionary.spec.ts b/test/ts/data-structures/dictionary.spec.ts new file mode 100644 index 00000000..28bf6615 --- /dev/null +++ b/test/ts/data-structures/dictionary.spec.ts @@ -0,0 +1,335 @@ +import 'mocha'; +import { expect } from 'chai'; +import { Dictionary } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('Dictionary', () => { + let dictionary: Dictionary; + + beforeEach(() => { + dictionary = new Dictionary(); + }); + + it('starts empty', () => { + expect(dictionary.size()).to.equal(0); + expect(dictionary.isEmpty()).to.equal(true); + }); + + it('sets undefined and null keys and values', () => { + const dict = new Dictionary(); + + expect(dict.set('undefined', undefined)).to.equal(false); + expect(dict.get('undefined')).to.equal(undefined); + + expect(dict.set('undefined', 1)).to.equal(true); + expect(dict.get('undefined')).to.equal(1); + + expect(dict.set('null', null)).to.equal(false); + expect(dict.get('null')).to.equal(undefined); + + expect(dict.set('null', 1)).to.equal(true); + expect(dict.get('null')).to.equal(1); + + dict.clear(); + expect(dict.set(undefined, undefined)).to.equal(false); + expect(dict.get(undefined)).to.equal(undefined); + + expect(dict.set(undefined, 1)).to.equal(false); + expect(dict.get(undefined)).to.equal(undefined); + + expect(dict.set(null, null)).to.equal(false); + expect(dict.get(null)).to.equal(undefined); + + expect(dict.set(null, 1)).to.equal(false); + expect(dict.get(null)).to.equal(undefined); + }); + + it('sets values with string key', () => { + const dict = new Dictionary(); + const min = 1; + const max = 5; + const size = max - min + 1; + + for (let i = min; i <= max; i++) { + expect(dict.set(`${i}`, i)).to.equal(true); + } + expect(dict.size()).to.equal(size); + + const keys = dict.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal((i + 1).toString(10)); + } + + dict.set('a', 1); + expect(dict.get('a')).to.equal(1); + }); + + it('sets values with number key', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + + const keys = dictionary.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal((i + 1)); + } + }); + + it('sets values with object', () => { + const dict = new Dictionary(); + const min = 0; + const max = 5; + const size = max - min; + const myObjList = []; + + for (let i = min; i < max; i++) { + myObjList.push(new MyObj(i, (i + 1))); + } + + for (let i = min; i < max; i++) { + expect(dict.set(myObjList[i], myObjList[i])).to.equal(true); + } + expect(dict.size()).to.equal(size); + + for (let i = min; i < max; i++) { + expect(dict.get(myObjList[i])).to.equal(myObjList[i]); + } + + const keys = dict.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal(myObjList[i]); + } + + const values = dict.values(); + expect(values.length).to.equal(size); + for (let i = 0; i < values.length; i++) { + expect(values[i]).to.equal(myObjList[i]); + } + }); + + function customToString(key: MyObj) { + return `####${key.toString()}`; + } + + it('sets values with custom toString function', () => { + const dict = new Dictionary(customToString); + const min = 0; + const max = 5; + const size = max - min; + const myObjList = []; + + for (let i = min; i < max; i++) { + myObjList.push(new MyObj(i, (i + 1))); + } + + for (let i = min; i < max; i++) { + expect(dict.set(myObjList[i], myObjList[i])).to.equal(true); + } + expect(dict.size()).to.equal(size); + + for (let i = min; i < max; i++) { + expect(dict.get(myObjList[i])).to.equal(myObjList[i]); + } + + const keys = dict.keys(); + expect(keys.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal(myObjList[i]); + } + + const values = dict.values(); + expect(values.length).to.equal(size); + for (let i = 0; i < values.length; i++) { + expect(values[i]).to.equal(myObjList[i]); + } + }); + + it('removes elements', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(dictionary.remove(i)).to.equal(true); + } + + // elements do not exist + for (let i = min; i <= max; i++) { + expect(dictionary.remove(i)).to.equal(false); + } + + expect(dictionary.isEmpty()).to.equal(true); + }); + + it('returns the correct size', () => { + expect(dictionary.size()).to.equal(0); + + const max = 5; + + for (let i = 1; i < max; i++) { + dictionary.set(i, i); + expect(dictionary.size()).to.equal(i); + } + for (let i = 1; i < max; i++) { + dictionary.remove(i); + expect(dictionary.size()).to.equal(max - i - 1); + } + + expect(dictionary.size()).to.equal(0); + expect(dictionary.isEmpty()).to.equal(true); + }); + + it('returns if element exists', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(dictionary.hasKey(i)).to.equal(true); + expect(dictionary.remove(i)).to.equal(true); + expect(dictionary.hasKey(i)).to.equal(false); + } + }); + + it('returns if it is empty', () => { + expect(dictionary.isEmpty()).to.equal(true); + + for (let i = 1; i < 5; i++) { + dictionary.set(i, i); + expect(dictionary.isEmpty()).to.equal(false); + } + + for (let i = 1; i < 5; i++) { + dictionary.remove(i); + expect(dictionary.isEmpty()).to.equal(!(i < 4)); + } + + expect(dictionary.size()).to.equal(0); + expect(dictionary.isEmpty()).to.equal(true); + }); + + it('clears the dictionary', () => { + dictionary.clear(); + expect(dictionary.isEmpty()).to.equal(true); + + dictionary.set(1, 1); + dictionary.set(2, 2); + + dictionary.clear(); + expect(dictionary.isEmpty()).to.equal(true); + }); + + it('returns values, keys and value pairs', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + + for (let i = min; i <= max; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + expect(dictionary.size()).to.equal(size); + + const keys = dictionary.keys(); + const values = dictionary.values(); + const valuePairs = dictionary.keyValues(); + expect(keys.length).to.equal(size); + expect(values.length).to.equal(size); + expect(valuePairs.length).to.equal(size); + for (let i = 0; i < keys.length; i++) { + expect(keys[i]).to.equal((i + 1)); + expect(values[i]).to.equal((i + 1)); + expect(valuePairs[i].key).to.equal((i + 1)); + expect(valuePairs[i].value).to.equal((i + 1)); + } + }); + + it('allows to iterate with forEach', () => { + for (let i = 1; i <= 5; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + + dictionary.forEach((k, v) => { + expect(dictionary.hasKey(k)).to.equal(true); + expect(dictionary.get(k)).to.equal(v); + }); + }); + + it('allows to iterate with forEach and interrupt', () => { + for (let i = 1; i <= 5; i++) { + expect(dictionary.set(i, i)).to.equal(true); + } + + const size = dictionary.keys().length; + + let index = 1; + dictionary.forEach((k, v) => { + expect(dictionary.hasKey(k)).to.equal(true); + expect(dictionary.get(k)).to.equal(v); + index++; + }); + expect(index).to.equal(size + 1); + + index = 1; + dictionary.forEach((k, v) => { + expect(dictionary.hasKey(k)).to.equal(true); + expect(dictionary.get(k)).to.equal(v); + index++; + return !(k % 3 === 0); + }); + expect(index).to.equal(size - 1); + }); + + it('returns toString primitive types', () => { + expect(dictionary.toString()).to.equal(''); + + dictionary.set(1, 1); + expect(dictionary.toString()).to.equal('[#1: 1]'); + + dictionary.set(2, 2); + expect(dictionary.toString()).to.equal('[#1: 1],[#2: 2]'); + + dictionary.clear(); + expect(dictionary.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const dict = new Dictionary(); + dict.set('el1', 1); + expect(dict.toString()).to.equal('[#el1: 1]'); + + dict.set('el2', 2); + expect(dict.toString()).to.equal('[#el1: 1],[#el2: 2]'); + }); + + it('returns toString objects', () => { + const dict = new Dictionary(); + expect(dict.toString()).to.equal(''); + + let myObj = new MyObj(1, 2); + dict.set(myObj, myObj); + expect(dict.toString()).to.equal('[#1|2: 1|2]'); + + myObj = new MyObj(3, 4); + dict.set(myObj, myObj); + expect(dict.toString()).to.equal('[#1|2: 1|2],[#3|4: 3|4]'); + }); + +}); diff --git a/test/ts/data-structures/doubly-linked-list.spec.ts b/test/ts/data-structures/doubly-linked-list.spec.ts new file mode 100644 index 00000000..76abb29a --- /dev/null +++ b/test/ts/data-structures/doubly-linked-list.spec.ts @@ -0,0 +1,406 @@ +import 'mocha'; +import { expect } from 'chai'; +import { DoublyLinkedList } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('DoublyLinkedList', () => { + let list: DoublyLinkedList; + let min: number; + let max: number; + + beforeEach(() => { + list = new DoublyLinkedList(); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = min; i <= max; i++) { + list.push(i); + } + } + + function verifyNode(current: any, i: number) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + + // verify next node + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + // TS strictNullChecks + if (current.next) { + expect(current.next.element).to.equal(i + 1); + } + } else { + expect(current.next).to.be.an('undefined'); + } + + // verify previous node + if (i > min) { + expect(current.prev).to.not.be.an('undefined'); + if (current.prev) { + expect(current.prev.element).to.equal(i - 1); + } + } else { + expect(current.prev).to.be.an('undefined'); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max; i++) { + expect(current).to.not.be.an('undefined'); + // TS strictNullChecks + if (current) { + verifyNode(current, i); + current = current.next; + } + } + verifyListFromTail(); + } + + function verifyListFromTail() { + let current = list.getTail(); + for (let i = max; i >= min; i--) { + expect(current).to.not.be.an('undefined'); + // TS strictNullChecks + if (current) { + verifyNode(current, i); + current = current.prev; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + expect(list.getTail()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max, 0)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + expect(list.insert(1, 1)).to.equal(false); + }); + + it('inserts elements invalid position not empty list', () => { + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(false); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i , i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + for (let i = min; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.getTail()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(1); + expect(current.prev).to.be.an('undefined'); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(3); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(3); + expect(current.next).to.be.an('undefined'); + expect(current.prev).to.not.be.an('undefined'); + if (current.prev) { + expect(current.prev.element).to.equal(1); + } + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the tail of the list', () => { + expect(list.getTail()).to.be.an('undefined'); + + list.push(1); + expect(list.getTail()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new DoublyLinkedList(); + ds.push('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new DoublyLinkedList(); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); + + it('returns inverseToString primitive types', () => { + expect(list.inverseToString()).to.equal(''); + + list.push(1); + expect(list.inverseToString()).to.equal('1'); + + list.push(2); + expect(list.inverseToString()).to.equal('2,1'); + + list.clear(); + expect(list.inverseToString()).to.equal(''); + }); + + it('returns inverseToString primitive types: string', () => { + const ds = new DoublyLinkedList(); + ds.push('el1'); + expect(ds.inverseToString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.inverseToString()).to.equal('el2,el1'); + }); + + it('returns inverseToString objects', () => { + const ds = new DoublyLinkedList(); + expect(ds.inverseToString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.inverseToString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.inverseToString()).to.equal('3|4,1|2'); + }); +}); diff --git a/test/ts/data-structures/hash-table-linear-probing-lazy.spec.ts b/test/ts/data-structures/hash-table-linear-probing-lazy.spec.ts new file mode 100644 index 00000000..7d004349 --- /dev/null +++ b/test/ts/data-structures/hash-table-linear-probing-lazy.spec.ts @@ -0,0 +1,388 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTableLinearProbingLazy } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('HashTableLinearProbingLazy', () => { + const A = 'Jonathan'; + const B = 'Jamie'; + const C = 'Sue'; + + it('starts empty', () => { + const hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + + it('generates hashcode', () => { + // numbers + let hashTable: any = new HashTableLinearProbingLazy(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + + // strings + hashTable = new HashTableLinearProbingLazy(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + + // objects + hashTable = new HashTableLinearProbingLazy(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + + it('puts undefined and null keys and values', () => { + const hashTable = new HashTableLinearProbingLazy(); + + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + + it('puts values with number key without collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableLinearProbingLazy(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + } + }); + + it('puts values with string key without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + + const table = hashTable.getTable(); + + expect(table[12].key).to.equal('1'); + expect(table[12].value).to.equal(1); + + expect(table[23].key).to.equal('10'); + expect(table[23].value).to.equal(10); + + expect(table[34].key).to.equal('100'); + expect(table[34].value).to.equal(100); + + expect(table[8].key).to.equal('1000'); + expect(table[8].value).to.equal(1000); + }); + + it('puts values with object key without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + + const table = hashTable.getTable(); + + expect(table[1].key).to.equal(myObjList[0]); + expect(table[1].value).to.equal(myObjList[0]); + + expect(table[3].key).to.equal(myObjList[1]); + expect(table[3].value).to.equal(myObjList[1]); + + expect(table[5].key).to.equal(myObjList[2]); + expect(table[5].value).to.equal(myObjList[2]); + + expect(table[7].key).to.equal(myObjList[3]); + expect(table[7].value).to.equal(myObjList[3]); + + expect(table[9].key).to.equal(myObjList[4]); + expect(table[9].value).to.equal(myObjList[4]); + }); + + function addValuesCollision() { + const hashTable = new HashTableLinearProbingLazy(); + + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.size()).to.equal(3); + + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + + expect(hashTable.size()).to.equal(3); + + return hashTable; + } + + it('puts values with collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableLinearProbingLazy(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 10)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 2); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 100)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 3); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + + expect(table[i + size].key).to.equal(i); + expect(table[i + size].value).to.equal(i + 10); + + expect(table[i + size * 2].key).to.equal(i); + expect(table[i + size * 2].value).to.equal(i + 100); + } + + addValuesCollision(); + }); + + it('removes elements without collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableLinearProbingLazy(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + + expect(hashTable.isEmpty()).to.equal(true); + }); + + function removeWithCollision(a: string, b: string, c: string) { + const hashTable = addValuesCollision(); + + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + + expect(hashTable.isEmpty()).to.equal(true); + } + + it('removes elements with collisions: scenario 1', () => { + // test all possibilities for removal + removeWithCollision(A, B, C); + removeWithCollision(A, C, B); + removeWithCollision(B, A, C); + removeWithCollision(B, C, A); + removeWithCollision(C, A, B); + removeWithCollision(C, B, A); + }); + + function addValuesCollision2() { + const hashTable = new HashTableLinearProbingLazy(); + + expect(hashTable.put(')', `parenthesis@email.com`)).to.equal(true); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put('+', `plus@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(',', `comma@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.put('-', `minus@email.com`)).to.equal(true); + expect(hashTable.put('0', `zero@email.com`)).to.equal(true); + + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.hashCode(')')).to.equal(4); + expect(hashTable.hashCode('+')).to.equal(6); + expect(hashTable.hashCode(',')).to.equal(7); + expect(hashTable.hashCode('-')).to.equal(8); + expect(hashTable.hashCode('0')).to.equal(11); + + expect(hashTable.size()).to.equal(8); + + const table = hashTable.getTable(); + expect(table[4].key).to.equal(')'); + expect(table[5].key).to.equal(A); + expect(table[6].key).to.equal('+'); + expect(table[7].key).to.equal(B); + expect(table[8].key).to.equal(','); + expect(table[9].key).to.equal(C); + expect(table[10].key).to.equal('-'); + expect(table[11].key).to.equal('0'); + + return hashTable; + } + + function verifyOtherKeys(hashTable: HashTableLinearProbingLazy) { + expect(hashTable.get(')')).to.not.equal(undefined); + expect(hashTable.get('+')).to.not.equal(undefined); + expect(hashTable.get(',')).to.not.equal(undefined); + expect(hashTable.get('-')).to.not.equal(undefined); + expect(hashTable.get('0')).to.not.equal(undefined); + } + + function removeWithCollision2(a: string, b: string, c: string) { + const hashTable = addValuesCollision2(); + + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + verifyOtherKeys(hashTable); + } + + it('removes elements with collisions: scenario 2', () => { + // test all possibilities for removal + removeWithCollision2(A, B, C); + removeWithCollision2(A, C, B); + removeWithCollision2(B, A, C); + removeWithCollision2(B, C, A); + removeWithCollision2(C, A, B); + removeWithCollision2(C, B, A); + }); + + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + + it('returns toString objects without collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal( + '{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}' + ); + }); + + it('returns toString with collisions', () => { + const hashTable = new HashTableLinearProbingLazy(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.put(1, 10); + expect(hashTable.toString()).to.equal( + '{1 => [#1: 1]},{2 => [#2: 2]},{3 => [#1: 10]}' + ); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); +}); diff --git a/test/ts/data-structures/hash-table-linear-probing.spec.ts b/test/ts/data-structures/hash-table-linear-probing.spec.ts new file mode 100644 index 00000000..77ed340f --- /dev/null +++ b/test/ts/data-structures/hash-table-linear-probing.spec.ts @@ -0,0 +1,388 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTableLinearProbing } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('HashTableLinearProbing', () => { + const A = 'Jonathan'; + const B = 'Jamie'; + const C = 'Sue'; + + it('starts empty', () => { + const hashTable = new HashTableLinearProbing(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + + it('generates hashcode', () => { + // numbers + let hashTable: any = new HashTableLinearProbing(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + + // strings + hashTable = new HashTableLinearProbing(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + + // objects + hashTable = new HashTableLinearProbing(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + + it('puts undefined and null keys and values', () => { + const hashTable = new HashTableLinearProbing(); + + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + + it('puts values with number key without collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableLinearProbing(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + } + }); + + it('puts values with string key without collisions', () => { + const hashTable = new HashTableLinearProbing(); + + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + + const table = hashTable.getTable(); + + expect(table[12].key).to.equal('1'); + expect(table[12].value).to.equal(1); + + expect(table[23].key).to.equal('10'); + expect(table[23].value).to.equal(10); + + expect(table[34].key).to.equal('100'); + expect(table[34].value).to.equal(100); + + expect(table[8].key).to.equal('1000'); + expect(table[8].value).to.equal(1000); + }); + + it('puts values with object key without collisions', () => { + const hashTable = new HashTableLinearProbing(); + + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + + const table = hashTable.getTable(); + + expect(table[1].key).to.equal(myObjList[0]); + expect(table[1].value).to.equal(myObjList[0]); + + expect(table[3].key).to.equal(myObjList[1]); + expect(table[3].value).to.equal(myObjList[1]); + + expect(table[5].key).to.equal(myObjList[2]); + expect(table[5].value).to.equal(myObjList[2]); + + expect(table[7].key).to.equal(myObjList[3]); + expect(table[7].value).to.equal(myObjList[3]); + + expect(table[9].key).to.equal(myObjList[4]); + expect(table[9].value).to.equal(myObjList[4]); + }); + + function addValuesCollision() { + const hashTable = new HashTableLinearProbing(); + + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.size()).to.equal(3); + + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + + expect(hashTable.size()).to.equal(3); + + return hashTable; + } + + it('puts values with collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableLinearProbing(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 10)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 2); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 100)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 3); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + + expect(table[i + size].key).to.equal(i); + expect(table[i + size].value).to.equal(i + 10); + + expect(table[i + size * 2].key).to.equal(i); + expect(table[i + size * 2].value).to.equal(i + 100); + } + + addValuesCollision(); + }); + + it('removes elements without collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableLinearProbing(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + + expect(hashTable.isEmpty()).to.equal(true); + }); + + function removeWithCollision(a: string, b: string, c: string) { + const hashTable = addValuesCollision(); + + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + + expect(hashTable.isEmpty()).to.equal(true); + } + + it('removes elements with collisions: scenario 1', () => { + // test all possibilities for removal + removeWithCollision(A, B, C); + removeWithCollision(A, C, B); + removeWithCollision(B, A, C); + removeWithCollision(B, C, A); + removeWithCollision(C, A, B); + removeWithCollision(C, B, A); + }); + + function addValuesCollision2() { + const hashTable = new HashTableLinearProbing(); + + expect(hashTable.put(')', `parenthesis@email.com`)).to.equal(true); + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put('+', `plus@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(',', `comma@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.put('-', `minus@email.com`)).to.equal(true); + expect(hashTable.put('0', `zero@email.com`)).to.equal(true); + + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + expect(hashTable.hashCode(')')).to.equal(4); + expect(hashTable.hashCode('+')).to.equal(6); + expect(hashTable.hashCode(',')).to.equal(7); + expect(hashTable.hashCode('-')).to.equal(8); + expect(hashTable.hashCode('0')).to.equal(11); + + expect(hashTable.size()).to.equal(8); + + const table = hashTable.getTable(); + expect(table[4].key).to.equal(')'); + expect(table[5].key).to.equal(A); + expect(table[6].key).to.equal('+'); + expect(table[7].key).to.equal(B); + expect(table[8].key).to.equal(','); + expect(table[9].key).to.equal(C); + expect(table[10].key).to.equal('-'); + expect(table[11].key).to.equal('0'); + + return hashTable; + } + + function verifyOtherKeys(hashTable: HashTableLinearProbing) { + expect(hashTable.get(')')).to.not.equal(undefined); + expect(hashTable.get('+')).to.not.equal(undefined); + expect(hashTable.get(',')).to.not.equal(undefined); + expect(hashTable.get('-')).to.not.equal(undefined); + expect(hashTable.get('0')).to.not.equal(undefined); + } + + function removeWithCollision2(a: string, b: string, c: string) { + const hashTable = addValuesCollision2(); + + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + verifyOtherKeys(hashTable); + + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + verifyOtherKeys(hashTable); + } + + it('removes elements with collisions: scenario 2', () => { + // test all possibilities for removal + removeWithCollision2(A, B, C); + removeWithCollision2(A, C, B); + removeWithCollision2(B, A, C); + removeWithCollision2(B, C, A); + removeWithCollision2(C, A, B); + removeWithCollision2(C, B, A); + }); + + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbing(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableLinearProbing(); + + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + + it('returns toString objects without collisions', () => { + const hashTable = new HashTableLinearProbing(); + + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal( + '{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}' + ); + }); + + it('returns toString with collisions', () => { + const hashTable = new HashTableLinearProbing(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.put(1, 10); + expect(hashTable.toString()).to.equal( + '{1 => [#1: 1]},{2 => [#2: 2]},{3 => [#1: 10]}' + ); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); +}); diff --git a/test/ts/data-structures/hash-table-separate-chaining.spec.ts b/test/ts/data-structures/hash-table-separate-chaining.spec.ts new file mode 100644 index 00000000..b7f72524 --- /dev/null +++ b/test/ts/data-structures/hash-table-separate-chaining.spec.ts @@ -0,0 +1,343 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTableSeparateChaining } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('HashTableSeparateChaining', () => { + const A = 'Jonathan'; + const B = 'Jamie'; + const C = 'Sue'; + + it('starts empty', () => { + const hashTable = new HashTableSeparateChaining(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + + it('generates hashcode', () => { + // numbers + let hashTable: any = new HashTableSeparateChaining(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + + // strings + hashTable = new HashTableSeparateChaining(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + + // objects + hashTable = new HashTableSeparateChaining(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + + it('puts undefined and null keys and values', () => { + const hashTable = new HashTableSeparateChaining(); + + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + + it('puts values with number key without collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableSeparateChaining(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + const linkedList = table[i]; + expect(linkedList.size()).to.equal(1); + const valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i); + } + }); + + it('puts values with string key without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + + const table = hashTable.getTable(); + + let linkedList = table[12]; + expect(linkedList.size()).to.equal(1); + let valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('1'); + expect(valuePair.element.value).to.equal(1); + + linkedList = table[23]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('10'); + expect(valuePair.element.value).to.equal(10); + + linkedList = table[34]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('100'); + expect(valuePair.element.value).to.equal(100); + + linkedList = table[8]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal('1000'); + expect(valuePair.element.value).to.equal(1000); + }); + + it('puts values with object key without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + + const table = hashTable.getTable(); + + let linkedList = table[1]; + expect(linkedList.size()).to.equal(1); + let valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[0]); + expect(valuePair.element.value).to.equal(myObjList[0]); + + linkedList = table[3]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[1]); + expect(valuePair.element.value).to.equal(myObjList[1]); + + linkedList = table[5]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[2]); + expect(valuePair.element.value).to.equal(myObjList[2]); + + linkedList = table[7]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[3]); + expect(valuePair.element.value).to.equal(myObjList[3]); + + linkedList = table[9]; + expect(linkedList.size()).to.equal(1); + valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(myObjList[4]); + expect(valuePair.element.value).to.equal(myObjList[4]); + }); + + it('puts values with collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableSeparateChaining(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 10)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 2); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i + 100)).to.equal(true); + } + expect(hashTable.size()).to.equal(size * 3); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + const linkedList = table[i]; + expect(linkedList.size()).to.equal(3); + + let valuePair = linkedList.getHead(); + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i); + + valuePair = valuePair.next; + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i + 10); + + valuePair = valuePair.next; + expect(valuePair.element.key).to.equal(i); + expect(valuePair.element.value).to.equal(i + 100); + } + }); + + it('removes elements without collisions', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTableSeparateChaining(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + + expect(hashTable.isEmpty()).to.equal(true); + }); + + function addValuesCollision() { + const hashTable = new HashTableSeparateChaining(); + + expect(hashTable.put(A, `${A}@email.com`)).to.equal(true); + expect(hashTable.put(B, `${B}@email.com`)).to.equal(true); + expect(hashTable.put(C, `${C}@email.com`)).to.equal(true); + expect(hashTable.size()).to.equal(3); + + const expectedHash = 5; + expect(hashTable.hashCode(A)).to.equal(expectedHash); + expect(hashTable.hashCode(B)).to.equal(expectedHash); + expect(hashTable.hashCode(C)).to.equal(expectedHash); + + expect(hashTable.getTable()[expectedHash].size()).to.equal(3); + + return hashTable; + } + + function removeWithCollision(a: string, b: string, c: string) { + const hashTable = addValuesCollision(); + + expect(hashTable.remove(a)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.not.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + + expect(hashTable.remove(b)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.not.equal(undefined); + + expect(hashTable.remove(c)).to.equal(true); + expect(hashTable.get(a)).to.equal(undefined); + expect(hashTable.get(b)).to.equal(undefined); + expect(hashTable.get(c)).to.equal(undefined); + + expect(hashTable.isEmpty()).to.equal(true); + } + + it('removes elements with collisions', () => { + // test all possibilities for removal + removeWithCollision(A, B, C); + removeWithCollision(A, C, B); + removeWithCollision(B, A, C); + removeWithCollision(B, C, A); + removeWithCollision(C, A, B); + removeWithCollision(C, B, A); + }); + + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + + it('returns toString primitive types without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + + it('returns toString objects without collisions', () => { + const hashTable = new HashTableSeparateChaining(); + + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal( + '{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}' + ); + }); + + it('returns toString with collisions', () => { + const hashTable = new HashTableSeparateChaining(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.put(1, 10); + expect(hashTable.toString()).to.equal('{1 => [#1: 1],[#1: 10]},{2 => [#2: 2]}'); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); +}); diff --git a/test/ts/data-structures/hash-table.spec.ts b/test/ts/data-structures/hash-table.spec.ts new file mode 100644 index 00000000..2dd56a3f --- /dev/null +++ b/test/ts/data-structures/hash-table.spec.ts @@ -0,0 +1,211 @@ +import 'mocha'; +import { expect } from 'chai'; +import { HashTable } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('HashTable', () => { + it('starts empty', () => { + const hashTable = new HashTable(); + expect(hashTable.size()).to.equal(0); + expect(hashTable.isEmpty()).to.equal(true); + }); + + it('generates hashcode', () => { + // numbers + let hashTable: any = new HashTable(); + expect(hashTable.hashCode(1)).to.equal(1); + expect(hashTable.hashCode(10)).to.equal(10); + expect(hashTable.hashCode(100)).to.equal(100); + expect(hashTable.hashCode(1000)).to.equal(1000); + + // strings + hashTable = new HashTable(); + expect(hashTable.hashCode('1')).to.equal(12); + expect(hashTable.hashCode('10')).to.equal(23); + expect(hashTable.hashCode('100')).to.equal(34); + expect(hashTable.hashCode('1000')).to.equal(8); + expect(hashTable.hashCode('a')).to.equal(23); + expect(hashTable.hashCode('A')).to.equal(28); + expect(hashTable.hashCode('Aba')).to.equal(1); + + // objects + hashTable = new HashTable(); + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + } + expect(hashTable.hashCode(myObjList[0])).to.equal(1); + expect(hashTable.hashCode(myObjList[1])).to.equal(3); + expect(hashTable.hashCode(myObjList[2])).to.equal(5); + expect(hashTable.hashCode(myObjList[3])).to.equal(7); + expect(hashTable.hashCode(myObjList[4])).to.equal(9); + }); + + it('puts undefined and null keys and values', () => { + const hashTable = new HashTable(); + + expect(hashTable.put('undefined', undefined)).to.equal(false); + expect(hashTable.get('undefined')).to.equal(undefined); + + expect(hashTable.put('undefined', 1)).to.equal(true); + expect(hashTable.get('undefined')).to.equal(1); + + expect(hashTable.put('null', null)).to.equal(false); + expect(hashTable.get('null')).to.equal(undefined); + + expect(hashTable.put('null', 1)).to.equal(true); + expect(hashTable.get('null')).to.equal(1); + + hashTable.clear(); + expect(hashTable.put(undefined, undefined)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(undefined, 1)).to.equal(false); + expect(hashTable.get(undefined)).to.equal(undefined); + + expect(hashTable.put(null, null)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + + expect(hashTable.put(null, 1)).to.equal(false); + expect(hashTable.get(null)).to.equal(undefined); + }); + + it('puts values with number key', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTable(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + const table = hashTable.getTable(); + for (let i = min; i <= max; i++) { + expect(table[i].key).to.equal(i); + expect(table[i].value).to.equal(i); + } + }); + + it('puts values with string key', () => { + const hashTable = new HashTable(); + + expect(hashTable.put('1', 1)).to.equal(true); + expect(hashTable.put('10', 10)).to.equal(true); + expect(hashTable.put('100', 100)).to.equal(true); + expect(hashTable.put('1000', 1000)).to.equal(true); + + const table = hashTable.getTable(); + + expect(table[12].key).to.equal('1'); + expect(table[12].value).to.equal(1); + + expect(table[23].key).to.equal('10'); + expect(table[23].value).to.equal(10); + + expect(table[34].key).to.equal('100'); + expect(table[34].value).to.equal(100); + + expect(table[8].key).to.equal('1000'); + expect(table[8].value).to.equal(1000); + }); + + it('puts values with object key', () => { + const hashTable = new HashTable(); + + const myObjList = []; + for (let i = 1; i <= 5; i++) { + myObjList.push(new MyObj(i, i + 1)); + expect(hashTable.put(myObjList[i - 1], myObjList[i - 1])).to.equal(true); + } + + const table = hashTable.getTable(); + + expect(table[1].key).to.equal(myObjList[0]); + expect(table[1].value).to.equal(myObjList[0]); + + expect(table[3].key).to.equal(myObjList[1]); + expect(table[3].value).to.equal(myObjList[1]); + + expect(table[5].key).to.equal(myObjList[2]); + expect(table[5].value).to.equal(myObjList[2]); + + expect(table[7].key).to.equal(myObjList[3]); + expect(table[7].value).to.equal(myObjList[3]); + + expect(table[9].key).to.equal(myObjList[4]); + expect(table[9].value).to.equal(myObjList[4]); + }); + + it('does NOT handle collision, replaces values', () => { + const hashTable = new HashTable(); + + for (let i = 0; i < 5; i++) { + expect(hashTable.put(1, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(1); + }); + + it('removes elements', () => { + const min = 1; + const max = 5; + const size = max - min + 1; + const hashTable = new HashTable(); + + for (let i = min; i <= max; i++) { + expect(hashTable.put(i, i)).to.equal(true); + } + expect(hashTable.size()).to.equal(size); + + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(true); + } + + // elements do not exist + for (let i = min; i <= max; i++) { + expect(hashTable.remove(i)).to.equal(false); + } + + expect(hashTable.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + const hashTable = new HashTable(); + + expect(hashTable.toString()).to.equal(''); + + hashTable.put(1, 1); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]}'); + + hashTable.put(2, 2); + expect(hashTable.toString()).to.equal('{1 => [#1: 1]},{2 => [#2: 2]}'); + + hashTable.clear(); + expect(hashTable.toString()).to.equal(''); + }); + + it('returns toString primitive types', () => { + const hashTable = new HashTable(); + + hashTable.put('el1', 1); + expect(hashTable.toString()).to.equal('{36 => [#el1: 1]}'); + + hashTable.put('el2', 2); + expect(hashTable.toString()).to.equal('{0 => [#el2: 2]},{36 => [#el1: 1]}'); + }); + + it('returns toString objects', () => { + const hashTable = new HashTable(); + + let myObj = new MyObj(1, 2); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal('{1 => [#1|2: 1|2]}'); + + myObj = new MyObj(3, 4); + hashTable.put(myObj, myObj); + expect(hashTable.toString()).to.equal( + '{1 => [#1|2: 1|2]},{5 => [#3|4: 3|4]}' + ); + }); +}); diff --git a/test/ts/data-structures/heap.spec.ts b/test/ts/data-structures/heap.spec.ts new file mode 100644 index 00000000..6a543fcd --- /dev/null +++ b/test/ts/data-structures/heap.spec.ts @@ -0,0 +1,75 @@ +import 'mocha'; +import { expect } from 'chai'; +import { MinHeap, heapSort } from '../../../src/ts/index'; + +describe('Heap', () => { + let heap: MinHeap; + + beforeEach(() => { + heap = new MinHeap(); + }); + + it('starts empty MinHeap', () => { + expect(heap.size()).to.equal(0); + expect(heap.isEmpty()).to.equal(true); + }); + + it('inserts values in the MinHeap', () => { + const resultArray = []; + for (let i = 1; i < 10; i++) { + resultArray.push(i); + heap.insert(i); + expect(heap.getAsArray()).to.deep.equal(resultArray); + } + }); + + it('finds the min value from the MinHeap', () => { + const resultArray = []; + for (let i = 10; i >= 1; i--) { + resultArray.push(i); + heap.insert(i); + expect(heap.findMinimum()).to.equal(i); + } + }); + + it('performs heapify in the MinHeap', () => { + const resultArray = []; + for (let i = 10; i >= 1; i--) { + resultArray.push(i); + } + expect(heap.heapify(resultArray)).to.deep.equal(resultArray); + }); + + it('extracts the min value from the MinHeap', () => { + let resultArray = []; + for (let i = 1; i < 10; i++) { + resultArray.push(i); + heap.insert(i); + expect(heap.getAsArray()).to.deep.equal(resultArray); + } + + resultArray = [ + [], + [2, 4, 3, 8, 5, 6, 7, 9], + [3, 4, 6, 8, 5, 9, 7], + [4, 5, 6, 8, 7, 9], + [5, 7, 6, 8, 9], + [6, 7, 9, 8], + [7, 8, 9], + [8, 9], + [9], + [] + ]; + + for (let i = 1; i < 10; i++) { + expect(heap.extract()).to.equal(i); + expect(heap.getAsArray()).to.deep.equal(resultArray[i]); + } + }); + + it('Heap Sort', () => { + const array = [3, 2, 5, 6, 1, 7, 8, 9]; + + expect(heapSort(array)).to.deep.equal([1, 2, 3, 5, 6, 7, 8, 9]); + }); +}); diff --git a/test/ts/data-structures/linked-list.spec.ts b/test/ts/data-structures/linked-list.spec.ts new file mode 100644 index 00000000..116abbd9 --- /dev/null +++ b/test/ts/data-structures/linked-list.spec.ts @@ -0,0 +1,330 @@ +import 'mocha'; +import { expect } from 'chai'; +import { LinkedList, util } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('LinkedList', () => { + let list: LinkedList; + let min: number; + let max: number; + + beforeEach(() => { + list = new LinkedList(util.defaultEquals); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = min; i <= max; i++) { + list.push(i); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max && current; i++) { + expect(current).to.not.be.an('undefined'); + if (current) { + // TS strictNullChecks + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + // TS strictNullChecks + expect(current.next.element).to.equal(i + 1); + } + } else { + expect(current.next).to.be.an('undefined'); + } + current = current.next; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max, 0)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + expect(list.insert(1, 1)).to.equal(false); + }); + + it('inserts elements invalid position not empty list', () => { + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(false); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i , i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + for (let i = min; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + } + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(1); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(3); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(3); + expect(current.next).to.be.an('undefined'); + } + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new LinkedList(); + ds.push('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.push('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new LinkedList(); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/my-obj.ts b/test/ts/data-structures/my-obj.ts new file mode 100644 index 00000000..ff633f2b --- /dev/null +++ b/test/ts/data-structures/my-obj.ts @@ -0,0 +1,7 @@ +export default class MyObj { + constructor(public el1: any, public el2: any) { } + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } +} + diff --git a/test/ts/data-structures/queue.spec.ts b/test/ts/data-structures/queue.spec.ts new file mode 100644 index 00000000..132f7280 --- /dev/null +++ b/test/ts/data-structures/queue.spec.ts @@ -0,0 +1,168 @@ +import 'mocha'; +import { expect } from 'chai'; +import Queue from '../../../src/ts/data-structures/queue'; + +describe('Queue', () => { + let queue: Queue; + + beforeEach(() => { + queue = new Queue(); + }); + + it('starts empty', () => { + expect(queue.size()).to.equal(0); + expect(queue.isEmpty()).to.equal(true); + }); + + it('enqueues elements', () => { + queue.enqueue(1); + expect(queue.size()).to.equal(1); + queue.enqueue(2); + expect(queue.size()).to.equal(2); + queue.enqueue(3); + expect(queue.size()).to.equal(3); + + expect(queue.isEmpty()).to.equal(false); + }); + + it('dequeue elements', () => { + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + expect(queue.dequeue()).to.equal(1); + expect(queue.dequeue()).to.equal(2); + expect(queue.dequeue()).to.equal(3); + expect(queue.dequeue()).to.equal(undefined); + }); + + it('implements FIFO logic', () => { + queue.enqueue(1); + expect(queue.peek()).to.equal(1); + queue.enqueue(2); + expect(queue.peek()).to.equal(1); + queue.enqueue(3); + expect(queue.peek()).to.equal(1); + + expect(queue.dequeue()).to.equal(1); + expect(queue.dequeue()).to.equal(2); + expect(queue.dequeue()).to.equal(3); + expect(queue.dequeue()).to.equal(undefined); + }); + + it('allows to peek at the front element in the queue without dequeuing it', () => { + expect(queue.peek()).to.equal(undefined); + + queue.enqueue(1); + expect(queue.peek()).to.equal(1); + + queue.enqueue(2); + expect(queue.peek()).to.equal(1); + + queue.dequeue(); + expect(queue.peek()).to.equal(2); + }); + + it('returns the correct size', () => { + expect(queue.size()).to.equal(0); + queue.enqueue(1); + expect(queue.size()).to.equal(1); + queue.enqueue(2); + expect(queue.size()).to.equal(2); + queue.enqueue(3); + expect(queue.size()).to.equal(3); + + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.size()).to.equal(3); + + queue.dequeue(); + expect(queue.size()).to.equal(2); + queue.dequeue(); + expect(queue.size()).to.equal(1); + queue.dequeue(); + expect(queue.size()).to.equal(0); + queue.dequeue(); + expect(queue.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(queue.isEmpty()).to.equal(true); + queue.enqueue(1); + expect(queue.isEmpty()).to.equal(false); + queue.enqueue(2); + expect(queue.isEmpty()).to.equal(false); + queue.enqueue(3); + expect(queue.isEmpty()).to.equal(false); + + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + expect(queue.isEmpty()).to.equal(false); + + queue.dequeue(); + expect(queue.isEmpty()).to.equal(false); + queue.dequeue(); + expect(queue.isEmpty()).to.equal(false); + queue.dequeue(); + expect(queue.isEmpty()).to.equal(true); + queue.dequeue(); + expect(queue.isEmpty()).to.equal(true); + }); + + it('clears the queue', () => { + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + + queue.enqueue(1); + queue.enqueue(2); + expect(queue.isEmpty()).to.equal(false); + + queue.clear(); + expect(queue.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(queue.toString()).to.equal(''); + + queue.enqueue(1); + expect(queue.toString()).to.equal('1'); + + queue.enqueue(2); + expect(queue.toString()).to.equal('1,2'); + + queue.clear(); + expect(queue.toString()).to.equal(''); + + const queueString = new Queue(); + queueString.enqueue('el1'); + expect(queueString.toString()).to.equal('el1'); + + queueString.enqueue('el2'); + expect(queueString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + class MyObj { + constructor(public el1: any, public el2: any) {} + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + const queueMyObj = new Queue(); + expect(queueMyObj.toString()).to.equal(''); + + queueMyObj.enqueue(new MyObj(1, 2)); + expect(queueMyObj.toString()).to.equal('1|2'); + + queueMyObj.enqueue(new MyObj(3, 4)); + expect(queueMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/red-black-tree.spec.ts b/test/ts/data-structures/red-black-tree.spec.ts new file mode 100644 index 00000000..d5091f86 --- /dev/null +++ b/test/ts/data-structures/red-black-tree.spec.ts @@ -0,0 +1,113 @@ +import { Colors } from './../../../src/ts/data-structures/models/red-black-node'; +import 'mocha'; +import { expect } from 'chai'; +import { RedBlackTree } from '../../../src/ts/index'; +import { RedBlackNode } from '../../../src/ts/data-structures/models/red-black-node'; + +describe('RedBlackTree', () => { + let tree: RedBlackTree; + + beforeEach(() => { + tree = new RedBlackTree(); + }); + + it('starts empty', () => { + expect(tree.getRoot()).to.equal(undefined); + }); + + it('inserts elements in the RedBlackTree', () => { + expect(tree.getRoot()).to.equal(undefined); + + let node; + + tree.insert(1); + assertNode(tree.getRoot(), 1, Colors.BLACK); + + tree.insert(2); + assertNode(tree.getRoot(), 1, Colors.BLACK); + assertNode(tree.getRoot().right, 2, Colors.RED); + + tree.insert(3); + assertNode(tree.getRoot(), 2, Colors.BLACK); + assertNode(tree.getRoot().right, 3, Colors.RED); + assertNode(tree.getRoot().left, 1, Colors.RED); + + tree.insert(4); + assertNode(tree.getRoot(), 2, Colors.BLACK); + assertNode(tree.getRoot().left, 1, Colors.BLACK); + assertNode(tree.getRoot().right, 3, Colors.BLACK); + assertNode(tree.getRoot().right.right, 4, Colors.RED); + + tree.insert(5); + assertNode(tree.getRoot(), 2, Colors.BLACK); + assertNode(tree.getRoot().left, 1, Colors.BLACK); + node = tree.getRoot().right; + assertNode(node, 4, Colors.BLACK); + assertNode(node.left, 3, Colors.RED); + assertNode(node.right, 5, Colors.RED); + + tree.insert(6); + assertNode(tree.getRoot(), 2, Colors.BLACK); + assertNode(tree.getRoot().left, 1, Colors.BLACK); + node = tree.getRoot().right; + assertNode(node, 4, Colors.RED); + assertNode(node.left, 3, Colors.BLACK); + assertNode(node.right, 5, Colors.BLACK); + assertNode(node.right.right, 6, Colors.RED); + + tree.insert(7); + assertNode(tree.getRoot(), 2, Colors.BLACK); + assertNode(tree.getRoot().left, 1, Colors.BLACK); + node = tree.getRoot().right; + assertNode(node, 4, Colors.RED); + assertNode(node.left, 3, Colors.BLACK); + assertNode(node.right, 6, Colors.BLACK); + assertNode(node.right.right, 7, Colors.RED); + assertNode(node.right.left, 5, Colors.RED); + + tree.insert(8); + assertNode(tree.getRoot(), 4, Colors.BLACK); + node = tree.getRoot().left; + assertNode(node, 2, Colors.RED); + assertNode(node.left, 1, Colors.BLACK); + assertNode(node.right, 3, Colors.BLACK); + node = tree.getRoot().right; + assertNode(node, 6, Colors.RED); + assertNode(node.left, 5, Colors.BLACK); + assertNode(node.right, 7, Colors.BLACK); + assertNode(node.right.right, 8, Colors.RED); + + tree.insert(9); + assertNode(tree.getRoot(), 4, Colors.BLACK); + node = tree.getRoot().left; + assertNode(node, 2, Colors.RED); + assertNode(node.left, 1, Colors.BLACK); + assertNode(node.right, 3, Colors.BLACK); + node = tree.getRoot().right; + assertNode(node, 6, Colors.RED); + assertNode(node.left, 5, Colors.BLACK); + assertNode(node.right, 8, Colors.BLACK); + assertNode(node.right.left, 7, Colors.RED); + assertNode(node.right.right, 9, Colors.RED); + + tree.insert(10); + assertNode(tree.getRoot(), 4, Colors.BLACK); + node = tree.getRoot().left; + assertNode(node, 2, Colors.BLACK); + assertNode(node.left, 1, Colors.BLACK); + assertNode(node.right, 3, Colors.BLACK); + node = tree.getRoot().right; + assertNode(node, 6, Colors.BLACK); + assertNode(node.left, 5, Colors.BLACK); + assertNode(node.right, 8, Colors.RED); + assertNode(node.right.left, 7, Colors.BLACK); + assertNode(node.right.right, 9, Colors.BLACK); + assertNode(node.right.right.right, 10, Colors.RED); + + }); + + function assertNode(node: RedBlackNode, key: number, color: Colors) { + expect(node.color).to.equal(color); + expect(node.key).to.equal(key); + } +}); diff --git a/test/ts/data-structures/set.spec.ts b/test/ts/data-structures/set.spec.ts new file mode 100644 index 00000000..7320cdfc --- /dev/null +++ b/test/ts/data-structures/set.spec.ts @@ -0,0 +1,352 @@ +import 'mocha'; +import { expect } from 'chai'; +import { Set } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('Set', () => { + let set: Set; + + beforeEach(() => { + set = new Set(); + }); + + it('starts empty', () => { + expect(set.size()).to.equal(0); + expect(set.isEmpty()).to.equal(true); + }); + + it('adds elements', () => { + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.size()).to.equal(i); + } + + expect(set.isEmpty()).to.equal(false); + }); + + it('does not allow duplicated elements', () => { + let expected = true; + for (let i = 1; i < 5; i++) { + expect(set.add(i)).to.equal(expected); + } + + expected = false; + for (let i = 1; i < 5; i++) { + expect(set.add(i)).to.equal(expected); + } + }); + + it('deletes elements', () => { + for (let i = 1; i < 5; i++) { + set.add(i); + } + + for (let i = 1; i < 5; i++) { + expect(set.delete(i)).to.equal(true); + } + + // elements do not exist + for (let i = 1; i < 5; i++) { + expect(set.delete(i)).to.equal(false); + } + + expect(set.isEmpty()).to.equal(true); + }); + + it('returns if element exists', () => { + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.has(i)).to.equal(true); + } + + for (let i = 1; i < 5; i++) { + expect(set.delete(i)).to.equal(true); + expect(set.has(i)).to.equal(false); + } + }); + + it('returns the correct size', () => { + expect(set.size()).to.equal(0); + + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.size()).to.equal(i); + } + + const max = 5; + for (let i = 1; i < max; i++) { + set.delete(i); + expect(set.size()).to.equal(max - i - 1); + } + + expect(set.size()).to.equal(0); + expect(set.isEmpty()).to.equal(true); + }); + + it('returns if it is empty', () => { + expect(set.isEmpty()).to.equal(true); + + for (let i = 1; i < 5; i++) { + set.add(i); + expect(set.isEmpty()).to.equal(false); + } + + for (let i = 1; i < 5; i++) { + set.delete(i); + expect(set.isEmpty()).to.equal(!(i < 4)); + } + + expect(set.size()).to.equal(0); + expect(set.isEmpty()).to.equal(true); + }); + + it('clears the set', () => { + set.clear(); + expect(set.isEmpty()).to.equal(true); + + set.add(1); + set.add(2); + + set.clear(); + expect(set.isEmpty()).to.equal(true); + }); + + function addValues(min: number, max: number) { + set = new Set(); + + for (let i = min; i <= max; i++) { + set.add(i); + } + + return set; + } + + it('union between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + let setResult = set1.union(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.union(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('union between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + let setResult = set1.union(set2); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.union(set1); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('union between different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + let setResult = set1.union(set2); + for (let i = 1; i <= 10; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.union(set1); + for (let i = 1; i <= 10; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('union between sets with common values', () => { + const set1 = addValues(1, 5); + const set2 = addValues(3, 6); + + let setResult = set1.union(set2); + for (let i = 1; i <= 6; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.union(set1); + for (let i = 1; i <= 6; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('intersection between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + let setResult = set1.intersection(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.intersection(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('intersection between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + let setResult = set1.intersection(set2); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.intersection(set1); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('intersection different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + let setResult = set1.intersection(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.intersection(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('intersection between sets with common values', () => { + const set1 = addValues(1, 5); + const set2 = addValues(3, 6); + + let setResult = set1.intersection(set2); + for (let i = 3; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.intersection(set1); + for (let i = 3; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('difference between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + let setResult = set1.difference(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.difference(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('difference between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + let setResult = set1.difference(set2); + expect(setResult.isEmpty()).to.equal(true); + + setResult = set2.difference(set1); + expect(setResult.isEmpty()).to.equal(true); + }); + + it('difference different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + let setResult = set1.difference(set2); + for (let i = 1; i <= 5; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.difference(set1); + for (let i = 6; i <= 10; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('difference between sets with common values', () => { + const set1 = addValues(1, 5); + const set2 = addValues(3, 6); + + let setResult = set1.difference(set2); + for (let i = 1; i <= 2; i++) { + expect(setResult.has(i)).to.equal(true); + } + + setResult = set2.difference(set1); + for (let i = 6; i <= 6; i++) { + expect(setResult.has(i)).to.equal(true); + } + }); + + it('isSubsetOf between empty sets', () => { + const set1 = new Set(); + const set2 = new Set(); + + expect(set1.isSubsetOf(set2)).to.equal(true); + expect(set2.isSubsetOf(set1)).to.equal(true); + }); + + it('isSubsetOf between equal sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(1, 5); + + expect(set1.isSubsetOf(set2)).to.equal(true); + expect(set2.isSubsetOf(set1)).to.equal(true); + }); + + it('isSubsetOf different sets', () => { + const set1 = addValues(1, 5); + const set2 = addValues(6, 10); + + expect(set1.isSubsetOf(set2)).to.equal(false); + expect(set2.isSubsetOf(set1)).to.equal(false); + }); + + it('isSubsetOf between sets with common values', () => { + const set1 = addValues(1, 8); + const set2 = addValues(3, 6); + expect(set1.isSubsetOf(set2)).to.equal(false); + expect(set2.isSubsetOf(set1)).to.equal(true); + + const set3 = addValues(1, 5); + const set4 = addValues(3, 6); + expect(set3.isSubsetOf(set4)).to.equal(false); + expect(set4.isSubsetOf(set3)).to.equal(false); + }); + + it('returns toString primitive types', () => { + expect(set.toString()).to.equal(''); + + set.add(1); + expect(set.toString()).to.equal('1'); + + set.add(2); + expect(set.toString()).to.equal('1,2'); + + set.clear(); + expect(set.toString()).to.equal(''); + }); + + it('returns toString primitive types: string', () => { + const ds = new Set(); + ds.add('el1'); + expect(ds.toString()).to.equal('el1'); + + ds.add('el2'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + const ds = new Set(); + expect(ds.toString()).to.equal(''); + + ds.add(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2'); + + ds.add(new MyObj(3, 4)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/sorted-linked-list.spec.ts b/test/ts/data-structures/sorted-linked-list.spec.ts new file mode 100644 index 00000000..02634f72 --- /dev/null +++ b/test/ts/data-structures/sorted-linked-list.spec.ts @@ -0,0 +1,341 @@ +import 'mocha'; +import { expect } from 'chai'; +import { SortedLinkedList, util } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('SortedLinkedList', () => { + let list: SortedLinkedList; + let min: number; + let max: number; + + beforeEach(() => { + list = new SortedLinkedList(); + min = 1; + max = 3; + }); + + function pushesElements() { + for (let i = max; i >= min; i--) { + list.push(i); + } + } + + function verifyList() { + let current = list.getHead(); + for (let i = min; i <= max && current; i++) { + expect(current).to.not.be.an('undefined'); + if (current) { + // TS strictNullChecks + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(i); + if (i < max) { + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + // TS strictNullChecks + expect(current.next.element).to.equal(i + 1); + } + } else { + expect(current.next).to.be.an('undefined'); + } + current = current.next; + } + } + } + + it('starts empty', () => { + expect(list.size()).to.equal(0); + expect(list.isEmpty()).to.equal(true); + expect(list.getHead()).to.be.an('undefined'); + }); + + it('pushes elements', () => { + pushesElements(); + verifyList(); + }); + + it('returns element at specific index: invalid position', () => { + // list is empty + expect(list.getElementAt(3)).to.be.an('undefined'); + }); + + it('returns element at specific index', () => { + let node; + + pushesElements(); + + for (let i = min; i <= max; i++) { + node = list.getElementAt(i - 1); + expect(node).to.not.be.an('undefined'); + if (node) { + expect(node.element).to.equal(i); + } + } + }); + + it('inserts elements first position empty list', () => { + const element = 1; + max = element; + expect(list.insert(element, 0)).to.equal(true); + verifyList(); + }); + + it('inserts elements first position not empty list', () => { + max = 2; + expect(list.insert(max)).to.equal(true); + + expect(list.insert(min, 0)).to.equal(true); + + verifyList(); + }); + + it('inserts elements invalid position empty list', () => { + // sorted list will ignore the index position + expect(list.insert(1, 1)).to.equal(true); + }); + + it('inserts elements invalid position not empty list', () => { + // sorted list will ignore the index position + const element = 1; + expect(list.insert(element, 0)).to.equal(true); + expect(list.insert(element, 2)).to.equal(true); + }); + + it('inserts elements in the middle of list', () => { + expect(list.insert(3, 0)).to.equal(true); + expect(list.insert(1, 0)).to.equal(true); + expect(list.insert(2, 1)).to.equal(true); + verifyList(); + }); + + it('inserts elements at the end of list', () => { + max = 5; + + for (let i = min; i <= max; i++) { + expect(list.insert(i , i - 1)).to.equal(true); + } + + verifyList(); + }); + + it('returns index of elements', () => { + let index; + + pushesElements(); + + for (let i = min; i <= max; i++) { + index = list.indexOf(i); + expect(index).to.equal(i - 1); + } + + expect(list.indexOf(max + 2)).to.equal(-1); + }); + + it('removes valid elements', () => { + let element; + + pushesElements(); + + for (let i = min; i <= max; i++) { + element = list.remove(i); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + } + }); + + it('removes invalid elements', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.remove(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position empty list', () => { + let element; + + for (let i = min; i <= max; i++) { + element = list.removeAt(i - 1); + expect(element).to.be.an('undefined'); + } + }); + + it('removes element invalid position not empty list', () => { + let element; + + pushesElements(); + + for (let i = max + 2; i <= max + 4; i++) { + element = list.removeAt(i); + expect(element).to.be.an('undefined'); + } + }); + + it('removes first element list single element', () => { + const value = 1; + list.push(value); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(value); + + expect(list.getHead()).to.be.an('undefined'); + expect(list.isEmpty()).to.equal(true); + }); + + it('removes first element list multiple elements', () => { + pushesElements(); + + const element = list.removeAt(0); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(min); + + min = 2; + verifyList(); + }); + + it('removes element from middle of list', () => { + pushesElements(); // 1, 2, 3 + + const element = list.removeAt(1); // element 2 + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(2); + + // list needs to be [1, 3] + let current = list.getHead(); + + // element 1 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(1); + expect(current.next).to.not.be.an('undefined'); + if (current.next) { + expect(current.next.element).to.equal(3); + current = current.next; + } + } + + // element 3 + expect(current).to.not.be.an('undefined'); + if (current) { + expect(current.element).to.not.be.an('undefined'); + expect(current.element).to.equal(3); + expect(current.next).to.be.an('undefined'); + } + }); + + it('removes element from end of list', () => { + let element; + + pushesElements(); + + const maxIndex = max; + for (let i = maxIndex; i >= min; i--) { + element = list.removeAt(i - 1); + expect(element).to.not.be.an('undefined'); + expect(element).to.equal(i); + max--; + verifyList(); + } + }); + + it('returns the head of the list', () => { + expect(list.getHead()).to.be.an('undefined'); + + list.push(1); + expect(list.getHead()).to.not.be.an('undefined'); + }); + + it('returns the correct size', () => { + expect(list.size()).to.equal(0); + + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.size()).to.equal(i); + } + + const size = max; + for (let i = min; i <= max; i++) { + list.remove(i); + expect(list.size()).to.equal(size - i); + } + + expect(list.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(list.isEmpty()).to.equal(true); + for (let i = min; i <= max; i++) { + list.push(i); + expect(list.isEmpty()).to.equal(false); + } + + for (let i = min; i < max; i++) { + list.remove(i); + expect(list.isEmpty()).to.equal(false); + } + list.remove(max); + expect(list.isEmpty()).to.equal(true); + + pushesElements(); + expect(list.isEmpty()).to.equal(false); + + list.clear(); + expect(list.isEmpty()).to.equal(true); + }); + + it('clears the list', () => { + expect(list.size()).to.equal(0); + list.clear(); + expect(list.size()).to.equal(0); + pushesElements(); + expect(list.size()).to.greaterThan(0); + list.clear(); + expect(list.size()).to.equal(0); + }); + + it('returns toString primitive types', () => { + expect(list.toString()).to.equal(''); + + list.push(1); + expect(list.toString()).to.equal('1'); + + list.push(2); + expect(list.toString()).to.equal('1,2'); + + list.clear(); + expect(list.toString()).to.equal(''); + }); + + function stringCompare(a: string, b: string): number { + return a.localeCompare(b); + } + + it('returns toString primitive types: string', () => { + + const ds = new SortedLinkedList(util.defaultEquals, stringCompare); + ds.push('el2'); + expect(ds.toString()).to.equal('el2'); + + ds.push('el1'); + expect(ds.toString()).to.equal('el1,el2'); + }); + + function myObjCompare(a: MyObj, b: MyObj): number { + return a.toString().localeCompare(b.toString()); + } + + it('returns toString objects', () => { + const ds = new SortedLinkedList(util.defaultEquals, myObjCompare); + expect(ds.toString()).to.equal(''); + + ds.push(new MyObj(3, 4)); + expect(ds.toString()).to.equal('3|4'); + + ds.push(new MyObj(1, 2)); + expect(ds.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/stack-array.spec.ts b/test/ts/data-structures/stack-array.spec.ts new file mode 100644 index 00000000..0894d7de --- /dev/null +++ b/test/ts/data-structures/stack-array.spec.ts @@ -0,0 +1,180 @@ +import 'mocha'; +import { expect } from 'chai'; +import StackArray from '../../../src/ts/data-structures/stack-array'; + +describe('StackArray', () => { + let stack: StackArray; + + beforeEach(() => { + stack = new StackArray(); + }); + + it('starts empty', () => { + expect(stack.size()).to.equal(0); + expect(stack.isEmpty()).to.equal(true); + }); + + it('pushes elements', () => { + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + expect(stack.isEmpty()).to.equal(false); + }); + + it('pops elements', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('implements LIFO logic', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('allows to peek at the top element in he stack without popping it', () => { + expect(stack.peek()).to.equal(undefined); + + stack.push(1); + expect(stack.peek()).to.equal(1); + + stack.push(2); + expect(stack.peek()).to.equal(2); + + stack.pop(); + expect(stack.peek()).to.equal(1); + }); + + it('returns the correct size', () => { + expect(stack.size()).to.equal(0); + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.size()).to.equal(2); + stack.pop(); + expect(stack.size()).to.equal(1); + stack.pop(); + expect(stack.size()).to.equal(0); + stack.pop(); + expect(stack.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(stack.isEmpty()).to.equal(true); + stack.push(1); + expect(stack.isEmpty()).to.equal(false); + stack.push(2); + expect(stack.isEmpty()).to.equal(false); + stack.push(3); + expect(stack.isEmpty()).to.equal(false); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('clears the stack', () => { + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('returns an Array', () => { + let stackArray = stack.toArray(); + expect(stackArray.length).to.equal(0); + + stack.push(1); + stack.push(2); + + stackArray = stack.toArray(); + expect(stackArray.length).to.equal(2); + + let i = 1; + stackArray.forEach(e => { + expect(e).to.equal(i); + i++; + }); + }); + + it('returns toString primitive types', () => { + expect(stack.toString()).to.equal(''); + + stack.push(1); + expect(stack.toString()).to.equal('1'); + + stack.push(2); + expect(stack.toString()).to.equal('1,2'); + + stack.clear(); + expect(stack.toString()).to.equal(''); + + const stackString = new StackArray(); + stackString.push('el1'); + expect(stackString.toString()).to.equal('el1'); + + stackString.push('el2'); + expect(stackString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + + class MyObj { + constructor(public el1: any, public el2: any) { } + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + const stackMyObj = new StackArray(); + expect(stackMyObj.toString()).to.equal(''); + + stackMyObj.push(new MyObj(1, 2)); + expect(stackMyObj.toString()).to.equal('1|2'); + + stackMyObj.push(new MyObj(3, 4)); + expect(stackMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/stack-linked-list.spec.ts b/test/ts/data-structures/stack-linked-list.spec.ts new file mode 100644 index 00000000..9889fb17 --- /dev/null +++ b/test/ts/data-structures/stack-linked-list.spec.ts @@ -0,0 +1,159 @@ +import 'mocha'; +import { expect } from 'chai'; +import { StackLinkedList } from '../../../src/ts/index'; +import MyObj from './my-obj'; + +describe('StackLinkedList', () => { + let stack: StackLinkedList; + + beforeEach(() => { + stack = new StackLinkedList(); + }); + + it('starts empty', () => { + expect(stack.size()).to.equal(0); + expect(stack.isEmpty()).to.equal(true); + }); + + it('pushes elements', () => { + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + expect(stack.isEmpty()).to.equal(false); + }); + + it('pops elements', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('implements LIFO logic', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('allows to peek at the top element in he stack without popping it', () => { + expect(stack.peek()).to.equal(undefined); + + stack.push(1); + expect(stack.peek()).to.equal(1); + + stack.push(2); + expect(stack.peek()).to.equal(2); + + stack.pop(); + expect(stack.peek()).to.equal(1); + }); + + it('returns the correct size', () => { + expect(stack.size()).to.equal(0); + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.size()).to.equal(2); + stack.pop(); + expect(stack.size()).to.equal(1); + stack.pop(); + expect(stack.size()).to.equal(0); + stack.pop(); + expect(stack.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(stack.isEmpty()).to.equal(true); + stack.push(1); + expect(stack.isEmpty()).to.equal(false); + stack.push(2); + expect(stack.isEmpty()).to.equal(false); + stack.push(3); + expect(stack.isEmpty()).to.equal(false); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('clears the stack', () => { + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + }); + + + it('returns toString primitive types', () => { + expect(stack.toString()).to.equal(''); + + stack.push(1); + expect(stack.toString()).to.equal('1'); + + stack.push(2); + expect(stack.toString()).to.equal('1,2'); + + stack.clear(); + expect(stack.toString()).to.equal(''); + + const stackString = new StackLinkedList(); + stackString.push('el1'); + expect(stackString.toString()).to.equal('el1'); + + stackString.push('el2'); + expect(stackString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + + const stackMyObj = new StackLinkedList(); + expect(stackMyObj.toString()).to.equal(''); + + stackMyObj.push(new MyObj(1, 2)); + expect(stackMyObj.toString()).to.equal('1|2'); + + stackMyObj.push(new MyObj(3, 4)); + expect(stackMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/data-structures/stack.spec.ts b/test/ts/data-structures/stack.spec.ts new file mode 100644 index 00000000..731e586c --- /dev/null +++ b/test/ts/data-structures/stack.spec.ts @@ -0,0 +1,163 @@ +import 'mocha'; +import { expect } from 'chai'; +import Stack from '../../../src/ts/data-structures/stack'; + +describe('Stack', () => { + let stack: Stack; + + beforeEach(() => { + stack = new Stack(); + }); + + it('starts empty', () => { + expect(stack.size()).to.equal(0); + expect(stack.isEmpty()).to.equal(true); + }); + + it('pushes elements', () => { + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + expect(stack.isEmpty()).to.equal(false); + }); + + it('pops elements', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('implements LIFO logic', () => { + stack.push(1); + stack.push(2); + stack.push(3); + + expect(stack.pop()).to.equal(3); + expect(stack.pop()).to.equal(2); + expect(stack.pop()).to.equal(1); + expect(stack.pop()).to.equal(undefined); + }); + + it('allows to peek at the top element in the stack without popping it', () => { + expect(stack.peek()).to.equal(undefined); + + stack.push(1); + expect(stack.peek()).to.equal(1); + + stack.push(2); + expect(stack.peek()).to.equal(2); + + stack.pop(); + expect(stack.peek()).to.equal(1); + }); + + it('returns the correct size', () => { + expect(stack.size()).to.equal(0); + stack.push(1); + expect(stack.size()).to.equal(1); + stack.push(2); + expect(stack.size()).to.equal(2); + stack.push(3); + expect(stack.size()).to.equal(3); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.size()).to.equal(2); + stack.pop(); + expect(stack.size()).to.equal(1); + stack.pop(); + expect(stack.size()).to.equal(0); + stack.pop(); + expect(stack.size()).to.equal(0); + }); + + it('returns if it is empty', () => { + expect(stack.isEmpty()).to.equal(true); + stack.push(1); + expect(stack.isEmpty()).to.equal(false); + stack.push(2); + expect(stack.isEmpty()).to.equal(false); + stack.push(3); + expect(stack.isEmpty()).to.equal(false); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + stack.push(3); + + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(false); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + stack.pop(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('clears the stack', () => { + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + + stack.push(1); + stack.push(2); + + stack.clear(); + expect(stack.isEmpty()).to.equal(true); + }); + + it('returns toString primitive types', () => { + expect(stack.toString()).to.equal(''); + + stack.push(1); + expect(stack.toString()).to.equal('1'); + + stack.push(2); + expect(stack.toString()).to.equal('1,2'); + + stack.clear(); + expect(stack.toString()).to.equal(''); + + const stackString = new Stack(); + stackString.push('el1'); + expect(stackString.toString()).to.equal('el1'); + + stackString.push('el2'); + expect(stackString.toString()).to.equal('el1,el2'); + }); + + it('returns toString objects', () => { + + class MyObj { + constructor(public el1: any, public el2: any) { } + toString() { + return `${this.el1.toString()}|${this.el2.toString()}`; + } + } + const stackMyObj = new Stack(); + expect(stackMyObj.toString()).to.equal(''); + + stackMyObj.push(new MyObj(1, 2)); + expect(stackMyObj.toString()).to.equal('1|2'); + + stackMyObj.push(new MyObj(3, 4)); + expect(stackMyObj.toString()).to.equal('1|2,3|4'); + }); +}); diff --git a/test/ts/others/balanced-symbols.spec.ts b/test/ts/others/balanced-symbols.spec.ts new file mode 100644 index 00000000..576432dd --- /dev/null +++ b/test/ts/others/balanced-symbols.spec.ts @@ -0,0 +1,42 @@ +import 'mocha'; +import { expect } from 'chai'; +import { parenthesesChecker } from '../../../src/ts/others/balanced-symbols'; + +describe('Balanced Symbols', () => { + + it('empty to be falsy', () => { + expect(parenthesesChecker('')).to.equal(true); + }); + + it('{ to be falsy', () => { + expect(parenthesesChecker('{')).to.equal(false); + }); + + it('} to be falsy', () => { + expect(parenthesesChecker('}')).to.equal(false); + }); + + it('11 to be falsy', () => { + expect(parenthesesChecker('11')).to.equal(false); + }); + + it('{11 to be falsy', () => { + expect(parenthesesChecker('{11')).to.equal(false); + }); + + it('{([1])} to be falsy', () => { + expect(parenthesesChecker('{([1])}')).to.equal(false); + }); + + it('{([])} to be truthy', () => { + expect(parenthesesChecker('{([])}')).to.equal(true); + }); + + it('{{([][])}()} to be truthy', () => { + expect(parenthesesChecker('{{([][])}()}')).to.equal(true); + }); + + it('[{()] to be falsy', () => { + expect(parenthesesChecker('[{()]')).to.equal(false); + }); +}); diff --git a/test/ts/others/base-converter.spec.ts b/test/ts/others/base-converter.spec.ts new file mode 100644 index 00000000..cec16bbe --- /dev/null +++ b/test/ts/others/base-converter.spec.ts @@ -0,0 +1,57 @@ +import 'mocha'; +import { expect } from 'chai'; +import { baseConverter, decimalToBinary } from '../../../src/ts/others/base-converter'; + +describe('Base Converter', () => { + it('decimalToBinary 1 -> 1', () => { + expect(decimalToBinary(1)).to.equal('1'); + }); + + it('decimalToBinary 2 -> 11', () => { + expect(decimalToBinary(2)).to.equal('10'); + }); + + it('decimalToBinary 233 -> 11101001', () => { + expect(decimalToBinary(233)).to.equal('11101001'); + }); + + it('decimalToBinary 10 -> 1010', () => { + expect(decimalToBinary(10)).to.equal('1010'); + }); + + it('decimalToBinary 1000 -> 1111101000', () => { + expect(decimalToBinary(1000)).to.equal('1111101000'); + }); + + it('baseConverter 100345, 2 -> 11000011111111001', () => { + expect(baseConverter(100345, 2)).to.equal('11000011111111001'); + }); + + it('baseConverter 100345, 8 -> 303771', () => { + expect(baseConverter(100345, 8)).to.equal('303771'); + }); + + it('baseConverter 100345, 16 -> 187F9', () => { + expect(baseConverter(100345, 16)).to.equal('187F9'); + }); + + it('baseConverter 100345, 7 -> 565360', () => { + expect(baseConverter(100345, 7)).to.equal('565360'); + }); + + it('baseConverter 100345, 20 -> CAH5', () => { + expect(baseConverter(100345, 20)).to.equal('CAH5'); + }); + + it('baseConverter 100345, 35 -> 2BW0', () => { + expect(baseConverter(100345, 35)).to.equal('2BW0'); + }); + + it('baseConverter 100345, 36 -> 25FD', () => { + expect(baseConverter(100345, 36)).to.equal('25FD'); + }); + + it('baseConverter 100345, 37 -> ', () => { + expect(baseConverter(100345, 37)).to.equal(''); + }); +}); diff --git a/test/ts/others/factorial.spec.ts b/test/ts/others/factorial.spec.ts new file mode 100644 index 00000000..d785d11c --- /dev/null +++ b/test/ts/others/factorial.spec.ts @@ -0,0 +1,26 @@ +import 'mocha'; +import { expect } from 'chai'; +import { factorialIterative, factorial } from '../../../src/ts/index'; + +describe('Factorial', () => { + + it('Iterative Factorial', () => { + expect(factorialIterative(-1)).to.equal(undefined); + expect(factorialIterative(0)).to.equal(1); + expect(factorialIterative(1)).to.equal(1); + expect(factorialIterative(2)).to.equal(2); + expect(factorialIterative(3)).to.equal(6); + expect(factorialIterative(4)).to.equal(24); + expect(factorialIterative(5)).to.equal(120); + }); + + it('Recursive Factorial', () => { + expect(factorial(-1)).to.equal(undefined); + expect(factorial(0)).to.equal(1); + expect(factorial(1)).to.equal(1); + expect(factorial(2)).to.equal(2); + expect(factorial(3)).to.equal(6); + expect(factorial(4)).to.equal(24); + expect(factorial(5)).to.equal(120); + }); +}); diff --git a/test/ts/others/fibonacci.spec.ts b/test/ts/others/fibonacci.spec.ts new file mode 100644 index 00000000..27ad81f0 --- /dev/null +++ b/test/ts/others/fibonacci.spec.ts @@ -0,0 +1,34 @@ +import 'mocha'; +import { expect } from 'chai'; +import { fibonacci, fibonacciIterative, fibonacciMemoization } from '../../../src/ts/index'; + +describe('Fibonacci', () => { + + it('Fibonacci Recursive', () => { + expect(fibonacci(-1)).to.equal(0); + expect(fibonacci(0)).to.equal(0); + expect(fibonacci(1)).to.equal(1); + expect(fibonacci(2)).to.equal(1); + expect(fibonacci(3)).to.equal(2); + expect(fibonacci(4)).to.equal(3); + }); + + it('Fibonacci Iterative', () => { + expect(fibonacciIterative(-1)).to.equal(0); + expect(fibonacciIterative(0)).to.equal(0); + expect(fibonacciIterative(1)).to.equal(1); + expect(fibonacciIterative(2)).to.equal(1); + expect(fibonacciIterative(3)).to.equal(2); + expect(fibonacciIterative(4)).to.equal(3); + }); + + it('Fibonacci with Memoization', () => { + expect(fibonacciMemoization(-1)).to.equal(0); + expect(fibonacciMemoization(0)).to.equal(0); + expect(fibonacciMemoization(1)).to.equal(1); + expect(fibonacciMemoization(2)).to.equal(1); + expect(fibonacciMemoization(3)).to.equal(2); + expect(fibonacciMemoization(4)).to.equal(3); + }); + +}); diff --git a/test/ts/others/hanoi.spec.ts b/test/ts/others/hanoi.spec.ts new file mode 100644 index 00000000..70f43fcd --- /dev/null +++ b/test/ts/others/hanoi.spec.ts @@ -0,0 +1,20 @@ +import 'mocha'; +import { expect } from 'chai'; +import { hanoi, hanoiStack } from '../../../src/ts/others/hanoi'; + +describe('Tower of Hanoi', () => { + + it('Hanoi', () => { + for (let i = 0; i < 10; i++) { + const result = hanoi(i, 'a', 'b', 'c'); + expect(result.length).to.equal(2 ** i - 1); + } + }); + + it('Hanoi with Stack', () => { + for (let i = 0; i < 10; i++) { + const result = hanoiStack(i); + expect(result.length).to.equal(2 ** i - 1); + } + }); +}); diff --git a/test/ts/others/hot-potato.spec.ts b/test/ts/others/hot-potato.spec.ts new file mode 100644 index 00000000..7ac9b827 --- /dev/null +++ b/test/ts/others/hot-potato.spec.ts @@ -0,0 +1,16 @@ +import { hotPotato } from '../../../src/ts/others/hot-potato'; +import 'mocha'; +import { expect } from 'chai'; + +describe('Hot Potato with Queue', () => { + + it('Hot potato game', () => { + const names = ['John', 'Jack', 'Camila', 'Ingrid', 'Carl']; + expect(hotPotato(names, 6).winner).to.equal('Ingrid'); + expect(hotPotato(names, 7).winner).to.equal('John'); + expect(hotPotato(names, 8).winner).to.equal('Jack'); + expect(hotPotato(names, 9).winner).to.equal('Ingrid'); + expect(hotPotato(names, 10).winner).to.equal('Carl'); + }); + +}); diff --git a/test/ts/others/palindrome-checker.spec.ts b/test/ts/others/palindrome-checker.spec.ts new file mode 100644 index 00000000..82451113 --- /dev/null +++ b/test/ts/others/palindrome-checker.spec.ts @@ -0,0 +1,20 @@ +import 'mocha'; +import { expect } from 'chai'; +import { palindromeChecker } from '../../../src/ts/others/palindrome-checker'; + +describe('Palindrome', () => { + + it('Palindrome Checker', () => { + expect(palindromeChecker('')).to.equal(false); + expect(palindromeChecker('a')).to.equal(true); + expect(palindromeChecker('aa')).to.equal(true); + expect(palindromeChecker('aba')).to.equal(true); + expect(palindromeChecker('ab')).to.equal(false); + expect(palindromeChecker('kayak')).to.equal(true); + expect(palindromeChecker('radar')).to.equal(true); + expect(palindromeChecker('level')).to.equal(true); + expect(palindromeChecker('Was it a car or a cat I saw')).to.equal(true); + expect(palindromeChecker('Step on no pets')).to.equal(true); + expect(palindromeChecker('Able was I ere I saw Elba')).to.equal(true); + }); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..0acebfa5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,57 @@ +{ + "compilerOptions": { + /* Basic Options */ + "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + // "module": "es2015", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["es2017"], /* Specify library files to be included in the compilation: */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist/ts", /* Redirect output structure to the directory. */ + // "rootDir": "./src/ts", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + // "strict": true /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + "noUnusedLocals": true, /* Report errors on unused locals. */ + "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + + /* Source Map Options */ + // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + }, + "exclude": ["node_modules", "dist"], + "include": ["src/ts/**/*"] +} diff --git a/tslint.json b/tslint.json new file mode 100644 index 00000000..449d62a0 --- /dev/null +++ b/tslint.json @@ -0,0 +1,115 @@ +{ + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "eofline": true, + "forin": true, + "import-blacklist": [ + true, + "rxjs" + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "typeof-compare": true, + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ] + } +} diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 00000000..6d033ef4 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,56 @@ +// @ts-check +/* eslint-disable */ +const webpack = require('webpack'); +const UglifyJsPlugin = require('uglifyjs-webpack-plugin');; +const path = require('path'); +const env = require('yargs').argv.env; + +let libraryName = 'PacktDataStructuresAlgorithms'; + +let plugins = [], + outputFile; + +if (env === 'build') { + // plugins.push(new UglifyJsPlugin({ minimize: true })); + outputFile = libraryName + '.min.js'; +} else { + outputFile = libraryName + '.js'; +} + +const config = { + entry: __dirname + '/src/js/index.js', + devtool: 'source-map', + output: { + path: __dirname + '/examples', + filename: outputFile, + library: libraryName, + libraryTarget: 'umd', + umdNamedDefine: true + }, + module: { + rules: [ + { + test: /(\.jsx|\.js)$/, + loader: 'babel-loader', + exclude: /(node_modules|bower_components)/ + } + ] + }, + resolve: { + modules: [path.resolve('./node_modules'), path.resolve('./src/js')], + extensions: ['.json', '.js'] + }, + optimization: { + minimizer: [ + // we specify a custom UglifyJsPlugin here to get source maps in production + new UglifyJsPlugin({ + cache: true, + parallel: true, + sourceMap: true + }) + ] + } + // plugins: plugins +}; + +module.exports = config;