diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..38bb7054 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,6 @@ +/runtimes/** +src/data-structures/maps/hash-maps/hashing.js +src/data-structures/maps/hash-maps/*-test.js +src/data-structures/maps/hash-maps/hash-map-*.js +src/data-structures/linked-lists/linked-list-*.js +src/data-structures/custom/lru-cache-*.js diff --git a/.eslintrc.js b/.eslintrc.js index 0c7f7af4..bfc96a26 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,23 +1,23 @@ module.exports = { - "extends": "airbnb-base", - "env": { - "jest": true + extends: 'airbnb-base', + env: { + jest: true + }, + globals: { + BigInt: true, }, rules: { // https://github.com/airbnb/javascript/issues/1089 // https://stackoverflow.com/a/35637900/684957 // allow to add properties to arguments - "no-param-reassign": [2, { "props": false }], + 'no-param-reassign': [2, { 'props': false }], // https://eslint.org/docs/rules/no-plusplus // allows unary operators ++ and -- in the afterthought (final expression) of a for loop. - "no-plusplus": [2, { "allowForLoopAfterthoughts": true }], + 'no-plusplus': [2, { 'allowForLoopAfterthoughts': true }], // Allow for..of - "no-restricted-syntax": [0, "ForOfStatement"], - }, - globals: { - BigInt: true, + 'no-restricted-syntax': [0, 'ForOfStatement'], } }; diff --git a/.travis.yml b/.travis.yml index 57f9ecfd..022566a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js +script: npm run ci node_js: - "node" - "lts/*" diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..2f829e08 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "workbench.colorCustomizations": { + "titleBar.activeBackground": "#f9e64f", + "titleBar.inactiveBackground": "#f9e64f99", + "titleBar.activeForeground": "#15202b", + "titleBar.inactiveForeground": "#15202b99" + } +} diff --git a/src/changelog.md b/CHANGELOG.md similarity index 84% rename from src/changelog.md rename to CHANGELOG.md index 1827a4b3..cd60971e 100644 --- a/src/changelog.md +++ b/CHANGELOG.md @@ -1,38 +1,51 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] -### Changed -- Fix picture on https://www.npmjs.com/package/dsa.js -### Added -- CI: travis -### Removed -- + +### Breaking changes + +### New Features +- Added Eslint and Travis ci + +### Patches +- Readme improvements +- Badges for npm versions and build status ## [1.1.0] - 2019-03-29 + ### Added + - README.md added because NPM packages doesn't read README.adoc - Public API to use the package `dsa.js` - This changelog ### Changed + - Updated dependencies (removed lodash since is not needed) ### Removed + - ## [1.0.0] - 2019-03-29 + ### Added + - Started the project - Book released - npm package published ### Changed + - + ### Removed + - diff --git a/README.md b/README.md index 818d57f8..8df0bb62 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,29 @@ # Data Structures and Algorithms in JavaScript +[![Build Status](https://travis-ci.com/amejiarosario/dsa.js.svg?branch=master)](https://travis-ci.com/amejiarosario/dsa.js) +[![npm version](https://badge.fury.io/js/dsa.js.svg)](https://badge.fury.io/js/dsa.js) + This repository covers the implementation of the classical algorithms and data structures in JavaScript. - +## Usage + +You can clone the repo or install the code from NPM: + +```sh +npm install dsa.js +``` + +and then you can import it into your programs or CLI + +```js +const { LinkedList, Queue, Stack } = require('dsa.js'); +``` + +For a full list of all the exposed data structures and algorithms [see](https://github.com/amejiarosario/dsa.js/blob/master/src/index.js). ## Book -You can check out the book that goes deeper into each topic and provide addtional illustrations and explanations. +You can check out the book that goes deeper into each topic and provide additional illustrations and explanations. - Algorithmic toolbox to avoid getting stuck while coding. - Explains data structures similarities and differences. @@ -21,65 +38,67 @@ We are covering the following data structures. [![Interactive Data Structures](https://user-images.githubusercontent.com/418605/46118890-ba721180-c1d6-11e8-82bc-6a671428b422.png)](https://embed.kumu.io/85f1a4de5fb8430a10a1bf9c5118e015) ### Linear Data Structures -1. **Arrays**: Built-in in most languages so not implemented here. + +1. **Arrays**: Built-in in most languages so not implemented here. [Post](https://adrianmejia.com/blog/2018/04/28/data-structures-time-complexity-for-beginners-arrays-hashmaps-linked-lists-stacks-queues-tutorial/#Array). -2. **Linked Lists**: each data node has a link to the next (and +2. **Linked Lists**: each data node has a link to the next (and previous). [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/data-structures/linked-lists/linked-list.js) | [Post](https://adrianmejia.com/blog/2018/04/28/data-structures-time-complexity-for-beginners-arrays-hashmaps-linked-lists-stacks-queues-tutorial/#Linked-Lists). -3. **Queue**: data flows in a "first-in, first-out" (FIFO) manner. +3. **Queue**: data flows in a "first-in, first-out" (FIFO) manner. [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/data-structures/queues/queue.js) | [Post](https://adrianmejia.com/blog/2018/04/28/data-structures-time-complexity-for-beginners-arrays-hashmaps-linked-lists-stacks-queues-tutorial/#Queues) -4. **Stacks**: data flows in a "last-in, first-out" (LIFO) manner. +4. **Stacks**: data flows in a "last-in, first-out" (LIFO) manner. [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/data-structures/stacks/stack.js) | [Post](https://adrianmejia.com/blog/2018/04/28/data-structures-time-complexity-for-beginners-arrays-hashmaps-linked-lists-stacks-queues-tutorial/#Stacks). ### Non-Linear Data Structures -1. **Trees**: data nodes has zero or more adjacent nodes a.k.a. + +1. **Trees**: data nodes has zero or more adjacent nodes a.k.a. children. Each node can only have one parent node otherwise is a graph not a tree. [Code](https://github.com/amejiarosario/algorithms.js/tree/master/src/data-structures/trees) | [Post](https://adrianmejia.com/blog/2018/06/11/data-structures-for-beginners-trees-binary-search-tree-tutorial/) - 1. **Binary Trees**: same as tree but only can have two children at + 1. **Binary Trees**: same as tree but only can have two children at most. [Code](https://github.com/amejiarosario/algorithms.js/tree/master/src/data-structures/trees) | [Post](https://adrianmejia.com/blog/2018/06/11/data-structures-for-beginners-trees-binary-search-tree-tutorial/#Binary-Trees) - 2. **Binary Search Trees** (BST): same as binary tree, but the + 2. **Binary Search Trees** (BST): same as binary tree, but the nodes value keep this order `left < parent < rigth`. [Code](https://github.com/amejiarosario/algorithms.js/blob/master/src/data-structures/trees/binary-search-tree.js) | [Post](https://adrianmejia.com/blog/2018/06/11/data-structures-for-beginners-trees-binary-search-tree-tutorial/#Binary-Search-Tree-BST) - 3. **AVL Trees**: Self-balanced BST to maximize look up time. + 3. **AVL Trees**: Self-balanced BST to maximize look up time. [Code](https://github.com/amejiarosario/algorithms.js/blob/master/src/data-structures/trees/avl-tree.js) | [Post](https://adrianmejia.com/blog/2018/07/16/self-balanced-binary-search-trees-with-avl-tree-data-structure-for-beginners/) - 4. **Red-Black Trees**: Self-balanced BST more loose than AVL to + 4. **Red-Black Trees**: Self-balanced BST more loose than AVL to maximize insertion speed. [Code](https://github.com/amejiarosario/algorithms.js/blob/master/src/data-structures/trees/red-black-tree.js) -2. **Maps**: key-value store. +2. **Maps**: key-value store. - 1. **Hash Maps**: implements map using a hash function. + 1. **Hash Maps**: implements map using a hash function. [Code](https://github.com/amejiarosario/algorithms.js/blob/master/src/data-structures/hash-maps/hashmap.js) | [Post](https://adrianmejia.com/blog/2018/04/28/data-structures-time-complexity-for-beginners-arrays-hashmaps-linked-lists-stacks-queues-tutorial/#HashMaps) - 2. **Tree Maps**: implement map using a self-balanced BST. + 2. **Tree Maps**: implement map using a self-balanced BST. [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/data-structures/maps/tree-maps/tree-map.js) -3. **Graphs**: data **nodes** that can have a connection or **edge** to +3. **Graphs**: data **nodes** that can have a connection or **edge** to zero or more adjacent nodes. Unlike trees, nodes can have multiple parents, loops. [Code](https://github.com/amejiarosario/algorithms.js/blob/master/src/data-structures/graphs/graph.js) @@ -88,39 +107,39 @@ We are covering the following data structures. ## Algorithms - - Sorting algorithms +- Sorting algorithms - - Bubble Sort. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/bubble-sort.js) + - Bubble Sort. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/bubble-sort.js) - - Insertion Sort. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/insertion-sort.js) + - Insertion Sort. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/insertion-sort.js) - - Selection Sort. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/selection-sort.js) + - Selection Sort. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/selection-sort.js) - - Merge Sort. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/merge-sort.js) + - Merge Sort. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/merge-sort.js) - - Quicksort. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/quick-sort.js) + - Quick sort. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/sorting/quick-sort.js) - - Greedy Algorithms +- Greedy Algorithms - - Fractional Knapsack Problem. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/knapsack-fractional.js) + - Fractional Knapsack Problem. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/knapsack-fractional.js) - - Divide and Conquer +- Divide and Conquer - - Fibonacci Numbers. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/fibonacci-recursive.js) + - Fibonacci Numbers. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/fibonacci-recursive.js) - - Dynamic Programming +- Dynamic Programming - - Fibonacci with memoization. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/fibanacci-dynamic-programming.js) + - Fibonacci with memoization. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/fibanacci-dynamic-programming.js) - - Backtracking algorithms +- Backtracking algorithms - - Word permutations. - [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/permutations-backtracking.js) + - Word permutations. + [Code](https://github.com/amejiarosario/dsa.js/blob/master/src/algorithms/permutations-backtracking.js) diff --git a/README.adoc b/deprecated-README.adoc similarity index 96% rename from README.adoc rename to deprecated-README.adoc index edbcb131..42c514f3 100644 --- a/README.adoc +++ b/deprecated-README.adoc @@ -3,6 +3,9 @@ :toclevels: 2 Adrian Mejia +image:https://travis-ci.com/amejiarosario/dsa.js.svg?branch=master["Build Status", link="https://travis-ci.com/amejiarosario/dsa.js"] +image:https://badge.fury.io/js/dsa.js.svg["npm version", link="https://badge.fury.io/js/dsa.js"] + This repository covers the implementation of the classical algorithms and data structures in JavaScript. toc::[] diff --git a/src/runtimes/array10.txt b/lab/array10.txt similarity index 100% rename from src/runtimes/array10.txt rename to lab/array10.txt diff --git a/src/runtimes/array1000.txt b/lab/array1000.txt similarity index 100% rename from src/runtimes/array1000.txt rename to lab/array1000.txt diff --git a/src/runtimes/array100k.txt b/lab/array100k.txt similarity index 100% rename from src/runtimes/array100k.txt rename to lab/array100k.txt diff --git a/src/runtimes/array1M.txt b/lab/array1M.txt similarity index 100% rename from src/runtimes/array1M.txt rename to lab/array1M.txt diff --git a/src/runtimes/linear/find-max.js b/lab/linear/find-max.js similarity index 100% rename from src/runtimes/linear/find-max.js rename to lab/linear/find-max.js diff --git a/src/runtimes/linear/get-min.js b/lab/linear/get-min.js similarity index 100% rename from src/runtimes/linear/get-min.js rename to lab/linear/get-min.js diff --git a/src/runtimes/linear/is-even.js b/lab/linear/is-even.js similarity index 100% rename from src/runtimes/linear/is-even.js rename to lab/linear/is-even.js diff --git a/src/runtimes/sortedArray1e1.txt b/lab/sortedArray1e1.txt similarity index 100% rename from src/runtimes/sortedArray1e1.txt rename to lab/sortedArray1e1.txt diff --git a/src/runtimes/sortedArray1e3.txt b/lab/sortedArray1e3.txt similarity index 100% rename from src/runtimes/sortedArray1e3.txt rename to lab/sortedArray1e3.txt diff --git a/src/runtimes/sortedArray1e4.txt b/lab/sortedArray1e4.txt similarity index 100% rename from src/runtimes/sortedArray1e4.txt rename to lab/sortedArray1e4.txt diff --git a/src/runtimes/test1e3.txt b/lab/test1e3.txt similarity index 100% rename from src/runtimes/test1e3.txt rename to lab/test1e3.txt diff --git a/src/runtimes/wrapper.js b/lab/wrapper.js similarity index 100% rename from src/runtimes/wrapper.js rename to lab/wrapper.js diff --git a/package-lock.json b/package-lock.json index 75a7c5fd..32c1ad24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "dsa.js", - "version": "0.0.1", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1555,12 +1555,14 @@ } }, "eslint-config-airbnb-base": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.1.0.tgz", - "integrity": "sha512-/vjm0Px5ZCpmJqnjIzcFb9TKZrKWz0gnuG/7Gfkt0Db1ELJR51xkZth+t14rYdqWgX836XbuxtArbIHlVhbLBA==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-13.1.0.tgz", + "integrity": "sha512-XWwQtf3U3zIoKO1BbHh6aUhJZQweOwSt4c2JrPDg9FP3Ltv3+YfEv7jIDB8275tVnO/qOHbfuYg3kzw6Je7uWw==", "dev": true, "requires": { - "eslint-restricted-globals": "^0.1.1" + "eslint-restricted-globals": "^0.1.1", + "object.assign": "^4.1.0", + "object.entries": "^1.0.4" } }, "eslint-import-resolver-node": { @@ -1573,73 +1575,49 @@ "resolve": "^1.5.0" }, "dependencies": { + "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 + }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } } } }, "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz", + "integrity": "sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w==", "dev": true, "requires": { "debug": "^2.6.8", - "pkg-dir": "^1.0.0" - }, - "dependencies": { - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - } + "pkg-dir": "^2.0.0" } }, "eslint-plugin-import": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.12.0.tgz", - "integrity": "sha1-2tMXgSktZmSyUxf9BJ0uKy8CIF0=", + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz", + "integrity": "sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A==", "dev": true, "requires": { "contains-path": "^0.1.0", - "debug": "^2.6.8", + "debug": "^2.6.9", "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.3.0", + "has": "^1.0.3", + "lodash": "^4.17.11", + "minimatch": "^3.0.4", "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" + "resolve": "^1.9.0" }, "dependencies": { "doctrine": { @@ -1652,6 +1630,15 @@ "isarray": "^1.0.0" } }, + "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" + } + }, "load-json-file": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", @@ -1664,6 +1651,12 @@ "strip-bom": "^3.0.0" } }, + "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", @@ -1695,12 +1688,12 @@ } }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz", + "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "^1.0.6" } }, "strip-bom": { @@ -2063,8 +2056,7 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "aproba": { "version": "1.2.0", @@ -2085,14 +2077,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2107,20 +2097,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -2237,8 +2224,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -2250,7 +2236,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -2265,7 +2250,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -2273,14 +2257,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -2299,7 +2281,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -2380,8 +2361,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -2393,7 +2373,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -2479,8 +2458,7 @@ "safe-buffer": { "version": "5.1.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -2516,7 +2494,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -2536,7 +2513,6 @@ "version": "3.0.1", "bundled": true, "dev": true, - "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -2580,14 +2556,12 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "yallist": { "version": "3.0.2", "bundled": true, - "dev": true, - "optional": true + "dev": true } } }, @@ -2755,6 +2729,12 @@ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, "has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -3905,7 +3885,8 @@ "lodash": { "version": "4.17.11", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true }, "lodash.sortby": { "version": "4.7.0", @@ -4254,6 +4235,41 @@ } } }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "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" + } + } + } + }, "object.getownpropertydescriptors": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", diff --git a/package.json b/package.json index f1eab949..9cdfe56e 100644 --- a/package.json +++ b/package.json @@ -2,24 +2,19 @@ "name": "dsa.js", "version": "1.1.0", "description": "Data Structures & Algorithms in JS", - "main": "./src/index.js", - "dependencies": { - - }, - "devDependencies": { - "benchmark": "2.1.4", - "eslint": "4.19.1", - "eslint-config-airbnb-base": "12.1.0", - "eslint-plugin-import": "2.12.0", - "eslint-plugin-jest": "21.17.0", - "jest": "23.6.0", - "textlint-plugin-asciidoctor": "1.0.2" + "author": "Adrian Mejia (https://adrianmejia.com)", + "homepage": "https://github.com/amejiarosario/dsa.js", + "repository": { + "type" : "git", + "url" : "https://github.com/amejiarosario/dsa.js.git" }, + "main": "./src/index.js", "scripts": { - "test": "jest src/ # jest # mocha src/**/*spec.js # jasmine JASMINE_CONFIG_PATH=jasmine.json # node jasmine-runner.js", + "test": "jest src/", "watch": "jest src/ --watch --coverage", "coverage": "jest src/ --coverage && open coverage/lcov-report/index.html", - "linter": "npx eslint --fix -f codeframe src/" + "lint": "npx eslint --fix --format codeframe src/", + "ci": "npx eslint src/ && npm test" }, "keywords": [ "algorithms", @@ -29,6 +24,20 @@ "linked lists", "binary search trees" ], - "author": "Adrian Mejia ", - "license": "ISC" + "license": "MIT", + "dependencies": { + + }, + "devDependencies": { + "benchmark": "2.1.4", + "eslint": "4.19.1", + "eslint-config-airbnb-base": "^13.1.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-jest": "21.17.0", + "jest": "23.6.0", + "textlint-plugin-asciidoctor": "1.0.2" + }, + "engines": { + "node" : ">=10.0.0" + } } diff --git a/src/algorithms/sorting/merge-sort.js b/src/algorithms/sorting/merge-sort.js index a4a08882..366f2590 100644 --- a/src/algorithms/sorting/merge-sort.js +++ b/src/algorithms/sorting/merge-sort.js @@ -16,8 +16,8 @@ function merge(array1, array2 = []) { // merge elements on a and b in asc order. Run-time O(a + b) for (let index = 0, i1 = 0, i2 = 0; index < mergedLength; index++) { // <1> - if (i2 >= array2.length || - (i1 < array1.length && array1[i1] <= array2[i2])) { + if (i2 >= array2.length + || (i1 < array1.length && array1[i1] <= array2[i2])) { mergedArray[index] = array1[i1]; // <2> i1 += 1; } else { @@ -45,7 +45,7 @@ function splitSort(array) { // base case if (size < 2) { return array; - } else if (size === 2) { + } if (size === 2) { return array[0] < array[1] ? array : [array[1], array[0]]; // <1> } diff --git a/src/data-structures/custom/lru-cache.js b/src/data-structures/custom/lru-cache.js index 817f3c1b..13638b6c 100644 --- a/src/data-structures/custom/lru-cache.js +++ b/src/data-structures/custom/lru-cache.js @@ -1,9 +1,12 @@ - /** - * Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and put. + * Design and implement a data structure for Least Recently Used (LRU) cache. + * It should support the following operations: get and put. - get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1. - put(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item. + get(key) - Get the value (will always be positive) of the key + if the key exists in the cache, otherwise return -1. + put(key, value) - Set or insert the value if the key is not already present. + When the cache reached its capacity, it should invalidate the least + recently used item before inserting a new item. Follow up: Could you do both operations in O(1) time complexity? @@ -27,46 +30,41 @@ * * @param {number} capacity */ -const LRUCache = function (capacity) { - this.map = new Map(); - this.capacity = capacity; -}; +class LRUCache { + constructor(capacity) { + this.map = new Map(); + this.capacity = capacity; + } -/** -* @param {number} key -* @return {number} -*/ -LRUCache.prototype.get = function (key) { - const value = this.map.get(key); - if (value) { - this.moveToTop(key); - return value; + get(key) { + const value = this.map.get(key); + if (value) { + this.moveToTop(key); + return value; + } + return -1; } - return -1; -}; -/** -* @param {number} key -* @param {number} value -* @return {void} -*/ -LRUCache.prototype.put = function (key, value) { - this.map.set(key, value); - this.rotate(key); -}; + put(key, value) { + this.map.set(key, value); + this.rotate(key); + } -LRUCache.prototype.rotate = function (key) { - this.moveToTop(key); - while (this.map.size > this.capacity) { - const it = this.map.keys(); - this.map.delete(it.next().value); + rotate(key) { + this.moveToTop(key); + while (this.map.size > this.capacity) { + const it = this.map.keys(); + this.map.delete(it.next().value); + } } -}; -LRUCache.prototype.moveToTop = function (key) { - if (this.map.has(key)) { - const value = this.map.get(key); - this.map.delete(key); - this.map.set(key, value); + moveToTop(key) { + if (this.map.has(key)) { + const value = this.map.get(key); + this.map.delete(key); + this.map.set(key, value); + } } -}; +} + +module.exports = LRUCache; diff --git a/src/data-structures/linked-lists/linked-list.js b/src/data-structures/linked-lists/linked-list.js index 8cee4abe..b9440791 100644 --- a/src/data-structures/linked-lists/linked-list.js +++ b/src/data-structures/linked-lists/linked-list.js @@ -1,5 +1,5 @@ -const Node = require('./node'); const util = require('util'); +const Node = require('./node'); // tag::constructor[] /** diff --git a/src/data-structures/maps/hash-maps/hash-map-1.js b/src/data-structures/maps/hash-maps/hash-map-1.js index c66109df..4deec02c 100644 --- a/src/data-structures/maps/hash-maps/hash-map-1.js +++ b/src/data-structures/maps/hash-maps/hash-map-1.js @@ -74,4 +74,3 @@ module.exports = HashMap; // assert.equal(hashMap.get('cat'), 8); // got overwritten by art 😱 // assert.equal(hashMap.get('rat'), 8); // got overwritten by art 😱 // assert.equal(hashMap.get('dog'), 8); // got overwritten by art 😱 - diff --git a/src/data-structures/maps/hash-maps/hashing.js b/src/data-structures/maps/hash-maps/hashing.js index cc4d0647..d2d104ea 100644 --- a/src/data-structures/maps/hash-maps/hashing.js +++ b/src/data-structures/maps/hash-maps/hashing.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + // tag::naiveHashCode[] /** * Naïve implementation of a non-cryptographic hashing function diff --git a/src/data-structures/queues/queue.js b/src/data-structures/queues/queue.js index 60d38178..2ef458a8 100644 --- a/src/data-structures/queues/queue.js +++ b/src/data-structures/queues/queue.js @@ -32,6 +32,7 @@ class Queue { dequeue() { return this.items.removeFirst(); } + // end::dequeue[] /** * Size of the queue @@ -66,4 +67,3 @@ queue.dequeue(); //↪️ b queue.dequeue(); //↪️ c // end::snippet[] // */ - diff --git a/src/data-structures/sets/array-set.js b/src/data-structures/sets/array-set.js index 8c11d069..4505c891 100644 --- a/src/data-structures/sets/array-set.js +++ b/src/data-structures/sets/array-set.js @@ -85,4 +85,3 @@ class ArraySet { } module.exports = ArraySet; - diff --git a/src/data-structures/sets/hash-set.js b/src/data-structures/sets/hash-set.js index 3327745b..4f139204 100644 --- a/src/data-structures/sets/hash-set.js +++ b/src/data-structures/sets/hash-set.js @@ -87,4 +87,3 @@ class HashMapSet { } module.exports = HashMapSet; - diff --git a/src/data-structures/sets/map-set.js b/src/data-structures/sets/map-set.js index b1c53485..f261892d 100644 --- a/src/data-structures/sets/map-set.js +++ b/src/data-structures/sets/map-set.js @@ -72,4 +72,3 @@ class MapSet { } module.exports = MapSet; - diff --git a/src/data-structures/stacks/stack-1.js b/src/data-structures/stacks/stack-1.js index c9022de8..51169097 100644 --- a/src/data-structures/stacks/stack-1.js +++ b/src/data-structures/stacks/stack-1.js @@ -37,4 +37,3 @@ Stack.prototype.push = Stack.prototype.add; Stack.prototype.pop = Stack.prototype.remove; module.exports = Stack; - diff --git a/src/data-structures/stacks/stack.js b/src/data-structures/stacks/stack.js index 9ab5a357..e96a6807 100644 --- a/src/data-structures/stacks/stack.js +++ b/src/data-structures/stacks/stack.js @@ -67,4 +67,3 @@ stack.remove(); //↪️ c stack.remove(); //↪️ a // end::snippet[] // */ - diff --git a/src/data-structures/trees/avl-tree.js b/src/data-structures/trees/avl-tree.js index fc6379b1..573095bd 100644 --- a/src/data-structures/trees/avl-tree.js +++ b/src/data-structures/trees/avl-tree.js @@ -24,14 +24,14 @@ function balance(node) { // left subtree is higher than right subtree if (node.left.balanceFactor > 0) { return rightRotation(node); - } else if (node.left.balanceFactor < 0) { + } if (node.left.balanceFactor < 0) { return leftRightRotation(node); } } else if (node.balanceFactor < -1) { // right subtree is higher than left subtree if (node.right.balanceFactor < 0) { return leftRotation(node); - } else if (node.right.balanceFactor > 0) { + } if (node.right.balanceFactor > 0) { return rightLeftRotation(node); } } diff --git a/src/data-structures/trees/binary-search-tree.js b/src/data-structures/trees/binary-search-tree.js index 12b562bc..43900c54 100644 --- a/src/data-structures/trees/binary-search-tree.js +++ b/src/data-structures/trees/binary-search-tree.js @@ -69,7 +69,7 @@ class BinarySearchTree { findNodeAndParent(value, node = this.root, parent = null) { if (!node || node.value === value) { return { found: node, parent }; - } else if (value < node.value) { + } if (value < node.value) { return this.findNodeAndParent(value, node.left, node); } return this.findNodeAndParent(value, node.right, node); diff --git a/src/data-structures/trees/red-black-tree.spec.js b/src/data-structures/trees/red-black-tree.spec.js index 1f010c1a..52d7f843 100644 --- a/src/data-structures/trees/red-black-tree.spec.js +++ b/src/data-structures/trees/red-black-tree.spec.js @@ -27,12 +27,9 @@ describe('RedBlackTree', () => { }); it('should balance tree by rotating left', () => { - const n1 = tree.add(1); - const n2 = tree.add(2); - const n3 = tree.add(3); - - // console.log(n3) - + tree.add(1); + tree.add(2); + tree.add(3); expect(tree.size).toBe(3); expect(tree.toArray()).toEqual([ diff --git a/src/runtimes/01-is-empty.js b/src/runtimes/01-is-empty.js index f15d9ef8..5c095ff0 100644 --- a/src/runtimes/01-is-empty.js +++ b/src/runtimes/01-is-empty.js @@ -1,5 +1,6 @@ /** * Return true if an array is empty and false otherwise + * Check for objects keys as well * @param {array|string|object} thing * @example * isEmpty() // => true @@ -30,4 +31,7 @@ function isEmpty(thing) { } // end::isEmpty[] -module.exports = isEmpty; +module.exports = { + isEmpty, + isEmpty2, +}; diff --git a/src/runtimes/02-binary-search.js b/src/runtimes/02-binary-search.js index 4a72c859..48783459 100644 --- a/src/runtimes/02-binary-search.js +++ b/src/runtimes/02-binary-search.js @@ -18,9 +18,9 @@ function binarySearchRecursive(array, search, offset = 0) { if (current === search) { return offset + half; - } else if (array.length < 2) { + } if (array.length < 2) { return -1; - } else if (search > current) { + } if (search > current) { const right = array.slice(half); return binarySearchRecursive(right, search, offset + half); } @@ -49,7 +49,7 @@ function binarySearchIterative(array, search) { if (current === search) { return currentIndex; - } else if (search > current) { + } if (search > current) { start = currentIndex; } else if (search < current) { end = currentIndex; @@ -62,24 +62,26 @@ function binarySearchIterative(array, search) { // const binarySearch = binarySearchRecursive; const binarySearch = binarySearchIterative; -function test() { - const directory = ['Adrian', 'Bella', 'Charlotte', 'Daniel', 'Emma', 'Hanna', 'Isabella', 'Jayden', 'Kaylee', 'Luke', 'Mia', 'Nora', 'Olivia', 'Paisley', 'Riley', 'Thomas', 'Wyatt', 'Xander', 'Zoe']; +// function test() { +// const directory = ['Adrian', 'Bella', 'Charlotte', 'Daniel', +// 'Emma', 'Hanna', 'Isabella', 'Jayden', 'Kaylee', 'Luke', 'Mia', +// 'Nora', 'Olivia', 'Paisley', 'Riley', 'Thomas', 'Wyatt', 'Xander', 'Zoe']; +// +// const assert = require('assert'); +// assert.equal(binarySearch([], 'not found'), -1); +// assert.equal(binarySearch([1], 2), -1); +// assert.equal(binarySearch([1], 1), 0); +// assert.equal(binarySearch([1, 2, 3], 1), 0); +// assert.equal(binarySearch([1, 2, 3], 2), 1); +// assert.equal(binarySearch([1, 2, 3], 3), 2); +// assert.equal(binarySearch([1, 2, 3], 31), -1); +// assert.equal(binarySearch(directory, 'Adrian'), 0); +// assert.equal(binarySearch(directory, 'Hanna'), 5); +// assert.equal(binarySearch(directory, 'Zoe'), 18); +// assert.equal(binarySearch(directory, 'not found'), -1); +// } - const assert = require('assert'); - assert.equal(binarySearch([], 'not found'), -1); - assert.equal(binarySearch([1], 2), -1); - assert.equal(binarySearch([1], 1), 0); - assert.equal(binarySearch([1, 2, 3], 1), 0); - assert.equal(binarySearch([1, 2, 3], 2), 1); - assert.equal(binarySearch([1, 2, 3], 3), 2); - assert.equal(binarySearch([1, 2, 3], 31), -1); - assert.equal(binarySearch(directory, 'Adrian'), 0); - assert.equal(binarySearch(directory, 'Hanna'), 5); - assert.equal(binarySearch(directory, 'Zoe'), 18); - assert.equal(binarySearch(directory, 'not found'), -1); -} - -test(); +// test(); -module.exports = binarySearch; +module.exports = { binarySearch, binarySearchIterative, binarySearchRecursive }; diff --git a/src/runtimes/06-multi-variable-equation-solver.js b/src/runtimes/06-multi-variable-equation-solver.js index 4470eb50..a2373ea1 100644 --- a/src/runtimes/06-multi-variable-equation-solver.js +++ b/src/runtimes/06-multi-variable-equation-solver.js @@ -19,7 +19,7 @@ function findXYZ({ start = 0, end = 10 } = {}) { for (let x = start; x < end; x++) { for (let y = start; y < end; y++) { for (let z = start; z < end; z++) { - if (3 * x + 9 * y + 8 * z === 79) { + if (3 * x + 9 * y + 8 * z === 79) { // eslint-disable-line solutions.push({ x, y, z }); } }