├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── README.md ├── gulpfile.babel.js ├── package.json ├── src ├── algorithms │ ├── arrayUtils.js │ └── sorting │ │ ├── bubble │ │ └── bubble.js │ │ ├── insertion │ │ └── insertion.js │ │ └── selection │ │ └── selection.js ├── data-structures │ ├── dictionaries │ │ └── Dictionary.js │ ├── linked-lists │ │ ├── DoublyLinkedList.js │ │ └── LinkedList.js │ ├── queues │ │ ├── HotPotato.js │ │ ├── PriorityQueue.js │ │ └── Queue.js │ ├── sets │ │ └── Set.js │ └── stacks │ │ ├── Dec2Bin.js │ │ └── Stack.js └── interview-questions │ ├── arrays │ ├── flatten.js │ ├── question1.js │ └── reordering.js │ ├── dom │ └── nodeX.html │ ├── events │ ├── debounce.js │ ├── emitter.js │ └── taxing.js │ └── html-css │ ├── edit-icon.html │ └── parent.html └── test ├── data-structures ├── dictionaries │ └── dictionaryTest.js ├── linked-lists │ ├── doublyLinkedListTest.js │ └── linkedListTest.js ├── queues │ ├── hotPotatoTest.js │ ├── priorityQueueTest.js │ └── queueTest.js ├── sets │ └── setTest.js └── stacks │ ├── dec2BinTest.js │ └── stackTest.js └── globalTest.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0", "stage-1"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "env": { 4 | "es6": true 5 | }, 6 | "parserOptions": { 7 | "sourceType": "module", 8 | "ecmaFeatures": { 9 | "jsx": true, 10 | "experimentalObjectRestSpread": true 11 | } 12 | }, 13 | "rules": { 14 | "accessor-pairs": 2, 15 | "array-callback-return": 2, 16 | "block-scoped-var": 2, 17 | "brace-style": [2, 1tbs], 18 | "callback-return": 2, 19 | "comma-dangle": [2, never], 20 | "complexity": [2, 8], 21 | "curly": 2, 22 | "dot-location": [2, property], 23 | "dot-notation": 2, 24 | "default-case": 2, 25 | "eol-last": 2, 26 | "eqeqeq": 2, 27 | "indent": [2, 2, {SwitchCase: 1}], 28 | "keyword-spacing": 2, 29 | "max-depth": [2, 6], 30 | "max-len": [2, 120, 4], 31 | "max-statements": ["error", 40, { "ignoreTopLevelFunctions": true }], 32 | "no-alert": 2, 33 | "no-bitwise": 0, 34 | "no-cond-assign": 2, 35 | "no-console": 0, 36 | "no-dupe-args": 2, 37 | "no-dupe-keys": 2, 38 | "no-duplicate-case": 2, 39 | "no-dupe-class-members": 2, 40 | "no-empty": 2, 41 | "no-empty-function": 2, 42 | "no-eq-null": 2, 43 | "no-eval": 2, 44 | "no-ex-assign": 2, 45 | "no-extend-native": 2, 46 | "no-extra-boolean-cast": 2, 47 | "no-extra-parens": 2, 48 | "no-extra-semi": 2, 49 | "no-fallthrough": 2, 50 | "no-floating-decimal": 2, 51 | "no-func-assign": 2, 52 | "no-implied-eval": 2, 53 | "no-implicit-globals": 2, 54 | "no-inner-declarations": [2, "both"], 55 | "no-invalid-regexp": 2, 56 | "no-irregular-whitespace": 2, 57 | "no-iterator": 2, 58 | "no-lone-blocks": 2, 59 | "no-loop-func": 2, 60 | "no-multi-spaces": 0, 61 | "no-multi-str": 2, 62 | "no-negated-in-lhs": 2, 63 | "no-new": 2, 64 | "no-new-func": 2, 65 | "no-new-wrappers": 2, 66 | "no-obj-calls": 2, 67 | "no-redeclare": 2, 68 | "no-regex-spaces": 2, 69 | "no-restricted-syntax": [2, WithStatement], 70 | "no-sparse-arrays": 2, 71 | "no-unexpected-multiline": 2, 72 | "no-unsafe-finally": 2, 73 | "no-unreachable": 2, 74 | "no-unused-expressions": 0, 75 | "no-unused-vars": [2, {args: none}], 76 | "no-void": 2, 77 | "no-undefined": 2, 78 | "prefer-const": 2, 79 | "prefer-template": 2, 80 | "quotes": [2, single, avoid-escape], 81 | "semi": [2, "always"], 82 | "space-before-blocks": 2, 83 | "strict": [2, global], 84 | "use-isnan": 2, 85 | "valid-jsdoc": 2, 86 | "valid-typeof": 2, 87 | "vars-on-top": 2, 88 | "wrap-iife": 2 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | npm-debug.log 4 | yarn.lock 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Curso: Algoritmos y Estructura de Datos 2 | 3 | ## Estructuras de Datos 4 | 5 | ### Pilas (Stacks) 6 | 7 | Una Pila (Stack) es una colección ordenada de elementos que sigue el principio LIFO (Last In First Out - Último en entrar primero en salir). 8 | 9 | Vídeo: https://www.youtube.com/watch?v=dgZhiYpcbME 10 | 11 | ### Colas (Queues) 12 | 13 | Una Cola (Queue) es una colección ordenada de elementos que sigue el principio FIFO (First In First Out - Primero en entrar primero en salir). 14 | 15 | Vídeo: https://www.youtube.com/watch?v=jWXh_GAEdsU 16 | 17 | ### Listas Enlazadas Simples (Linked Lists) 18 | 19 | Las listas enlazadas (linked lists) son estructuras de datos similares a los Arrays pero con la diferencia que el acceso a un elemento no se hace mediante un índice sino mediante un puntero. La asignación de memoria es hecha durante la ejecución. 20 | 21 | Vídeo: https://www.youtube.com/watch?v=KRtsuoa9AOo 22 | 23 | ### Conjuntos (Sets) 24 | 25 | Un set (colección) es una colección de elementos que no están ordenados y que consta de elementos únicos (no pueden ser repetidos). Esta estructura de datos utiliza el mismo concepto Matemático pero aplicado a las Ciencias de la Computación. 26 | 27 | Operaciones: 28 | 29 | * **Union**: Dados dos sets, retorna un nuevo set con los elementos de ambos. 30 | 31 | * **Intersección**: Dados dos sets, retorna un nuevo set con los elementos existentes en ambos sets. 32 | 33 | * **Diferencia**: Dados dos sets, retorna un nuevo set con todos los elementos que existen en el primer set pero no existen en el segundo. 34 | 35 | * **SubConjunto**: Confirma si un set es subconjunto de otro. 36 | 37 | Vídeo: https://www.youtube.com/watch?v=ZLBUQwqRsd8 38 | -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | // NPM Dependencies 2 | import babel from 'gulp-babel'; 3 | import eslint from 'gulp-eslint'; 4 | import gulp from 'gulp'; 5 | import mocha from 'gulp-mocha'; 6 | 7 | // Mocha task 8 | gulp.task('test', () => { 9 | return gulp.src([ 10 | 'test/**/*Test.js' 11 | ]) 12 | .pipe(babel()) 13 | .pipe(mocha()); 14 | }); 15 | 16 | // Linter task 17 | gulp.task('analyze', () => { 18 | return gulp.src([ 19 | 'src/**/*.js', 20 | 'test/**/*Test.js' 21 | ]) 22 | .pipe(eslint()) 23 | .pipe(eslint.format()) 24 | .pipe(eslint.failAfterError()); 25 | }); 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "algorithms-and-data-structures", 3 | "version": "0.0.1", 4 | "author": "Carlos Santana", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/MilkZoft/algorithms-and-data-structures.git" 9 | }, 10 | "scripts": { 11 | "precommit": "gulp analyze", 12 | "prepush": "gulp test", 13 | "postmerge": "yarn", 14 | "postrewrite": "yarn" 15 | }, 16 | "dependencies": { 17 | "babel-cli": "6.23.0", 18 | "babel-core": "^6.23.1", 19 | "babel-eslint": "^7.1.1", 20 | "babel-preset-es2015": "^6.22.0", 21 | "babel-preset-stage-0": "^6.22.0", 22 | "babel-preset-stage-1": "^6.22.0", 23 | "babel-register": "^6.23.0", 24 | "chai": "^3.5.0", 25 | "eslint": "^3.16.1", 26 | "eslint-plugin-babel": "^4.0.1", 27 | "gulp": "^3.9.1", 28 | "gulp-babel": "^6.1.2", 29 | "gulp-eslint": "^3.0.1", 30 | "gulp-mocha": "^4.0.1", 31 | "husky": "^0.13.1", 32 | "mocha": "^3.2.0" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/algorithms/arrayUtils.js: -------------------------------------------------------------------------------- 1 | let spins = 1; 2 | 3 | export function createArray(size) { 4 | const arr = []; 5 | 6 | for (let i = size; i > 0; i--) { 7 | arr.push(i); 8 | } 9 | 10 | return arr; 11 | } 12 | 13 | export function swap(indexA, indexB, array) { 14 | const tmp = array[indexA]; 15 | array[indexA] = array[indexB]; 16 | array[indexB] = tmp; 17 | 18 | console.log(spins++, '-', indexA, indexB, 'SWAPPING===', tmp, array[indexA]); 19 | 20 | return array; 21 | } 22 | -------------------------------------------------------------------------------- /src/algorithms/sorting/bubble/bubble.js: -------------------------------------------------------------------------------- 1 | import { createArray, swap } from '../../arrayUtils'; 2 | 3 | let array = createArray(10); 4 | 5 | console.log('UNSORTED', array.toString(), '\n'); 6 | 7 | bubleSort(); 8 | 9 | console.log('\nSORTED', array.toString()); 10 | 11 | function bubleSort() { 12 | for (let i = 0; i < array.length; i++) { 13 | for (let j = 0; j < array.length - 1; j++) { 14 | if (array[j] > array[j + 1]) { 15 | array = swap(j, j + 1, array); 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/algorithms/sorting/insertion/insertion.js: -------------------------------------------------------------------------------- 1 | import { createArray } from '../../arrayUtils'; 2 | 3 | const array = createArray(5); 4 | 5 | console.log('UNSORTED', array.toString(), '\n'); 6 | 7 | insertionSort(); 8 | 9 | console.log('\nSORTED', array.toString()); 10 | 11 | function insertionSort() { 12 | let j; 13 | let tmp; 14 | 15 | for (let i = 1; i < array.length; i++) { 16 | j = i; 17 | tmp = array[i]; 18 | 19 | while (j > 0 && array[j - 1] > tmp) { 20 | array[j] = array[j - 1]; 21 | console.log(array[j]); 22 | j--; 23 | } 24 | array[j] = tmp; 25 | console.log(array[j], 'Insertado'); 26 | console.log(array); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/algorithms/sorting/selection/selection.js: -------------------------------------------------------------------------------- 1 | import { createArray, swap } from '../../arrayUtils'; 2 | 3 | let array = createArray(1000); 4 | 5 | console.log('UNSORTED', array.toString(), '\n'); 6 | 7 | selectionSort(); 8 | 9 | console.log('\nSORTED', array.toString()); 10 | 11 | function selectionSort() { 12 | let indexMin; 13 | 14 | for (let i = 0; i < array.length - 1; i++) { 15 | indexMin = i; 16 | 17 | for (let j = i; j < array.length; j++) { 18 | if (array[indexMin] > array[j]) { 19 | indexMin = j; 20 | } 21 | } 22 | 23 | if (i !== indexMin) { 24 | array = swap(i, indexMin, array); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/data-structures/dictionaries/Dictionary.js: -------------------------------------------------------------------------------- 1 | export default function Dictionary() { 2 | let items = {}; 3 | 4 | this.set = (key, value) => { 5 | items[key] = value; 6 | }; 7 | 8 | this.delete = key => { 9 | if (this.has(key)) { 10 | delete items[key]; 11 | 12 | return true; 13 | } 14 | 15 | return false; 16 | }; 17 | 18 | this.get = key => { 19 | return this.has(key) ? items[key] : false; 20 | }; 21 | 22 | this.values = () => { 23 | const values = []; 24 | 25 | for (const key in items) { 26 | if (this.has(key)) { 27 | values.push(items[key]); 28 | } 29 | } 30 | 31 | return values; 32 | }; 33 | 34 | this.keys = () => { 35 | return Object.keys(items); 36 | }; 37 | 38 | this.size = () => { 39 | return Object.keys(items).length; 40 | }; 41 | 42 | this.getItems = () => { 43 | return items; 44 | }; 45 | 46 | this.has = key => { 47 | return key in items; 48 | }; 49 | 50 | this.clear = () => { 51 | items = {}; 52 | }; 53 | } 54 | -------------------------------------------------------------------------------- /src/data-structures/linked-lists/DoublyLinkedList.js: -------------------------------------------------------------------------------- 1 | export default class DoublyLinkedList { 2 | constructor() { 3 | this.head = null; 4 | this.tail = null; 5 | this.listSize = 0; 6 | } 7 | 8 | Node(element) { 9 | return { 10 | element, 11 | next: null, 12 | previous: null 13 | }; 14 | } 15 | 16 | append(element) { 17 | const node = this.Node(element); 18 | let current; 19 | 20 | // Si la lista esta vacia (Primer elemento) 21 | if (this.head === null) { 22 | this.head = node; 23 | } else { 24 | // Si ya tiene datos comenzamos a recorrer la lista desde head 25 | current = this.head; 26 | 27 | // Mientras exista un element en el node.next (cuando llegue a null sera el final de la lista) 28 | while (current.next) { 29 | // current tome el valor del proximo elemento (next) 30 | current = current.next; 31 | } 32 | 33 | // Ahora current ya tiene el último elemento y asignamos el nuevo elemento a su next 34 | current.next = node; 35 | } 36 | 37 | // Incrementamos el tamaño de la lista 38 | this.listSize++; 39 | } 40 | 41 | insert(position, element) { 42 | // Validar el rango 43 | if (position >= 0 && position <= this.listSize) { 44 | const node = this.Node(element); 45 | let current = this.head; 46 | let previous; 47 | let index = 0; 48 | 49 | // Agregar un elemento al inicio la lista 50 | if (position === 0) { 51 | if (!this.head) { 52 | this.head = node; 53 | this.tail = node; 54 | } else { 55 | node.next = current; 56 | current.previous = node; 57 | this.head = node; 58 | } 59 | // Último elemento 60 | } else if (position === this.listSize) { 61 | current = tail; 62 | current.next = node; 63 | node.previous = current; 64 | this.tail = node; 65 | } else { 66 | while (index++ < position) { 67 | previous = current; 68 | current = current.next; 69 | } 70 | 71 | node.next = current; 72 | previous.next = node; 73 | 74 | current.previous = node; 75 | node.previous = previous; 76 | } 77 | 78 | // Incrementamos el tamaño de la lista 79 | this.listSize++; 80 | 81 | return true; 82 | } 83 | 84 | return false; 85 | } 86 | 87 | removeAt(position) { 88 | // Validar el rango 89 | if (position > -1 && position < this.listSize) { 90 | let current = this.head; 91 | let previous; 92 | let index = 0; 93 | 94 | // Quitamos el primer elemento 95 | if (position === 0) { 96 | this.head = current.next; 97 | 98 | if (this.listSize === 1) { 99 | this.tail = null; 100 | } else { 101 | this.head.previous = null; 102 | } 103 | } else if (position === this.listSize - 1) { 104 | current = this.tail; 105 | this.tail = current.previous; 106 | this.tail.next = null; 107 | } else { 108 | // Recorremos la lista hasta la posicion indicada 109 | while (index++ < position) { 110 | previous = current; 111 | current = current.next; 112 | } 113 | 114 | // Enlazamos el elemento anterior con el next del current (saltamos el elemento para eliminarlo) 115 | previous.next = current.next; 116 | current.next.previous = previous; 117 | } 118 | 119 | this.listSize--; 120 | 121 | // Retornamos el elemento eliminado 122 | return current.element; 123 | } 124 | 125 | return false; 126 | } 127 | 128 | remove(element) { 129 | const index = this.indexOf(element); 130 | 131 | return this.removeAt(index); 132 | } 133 | 134 | indexOf(element) { 135 | let current = this.head; 136 | let index = 0; 137 | 138 | while (current) { 139 | if (current.element === element) { 140 | return index; 141 | } 142 | 143 | index++; 144 | current = current.next; 145 | } 146 | 147 | return -1; 148 | } 149 | 150 | hasElements() { 151 | return this.listSize > 0; 152 | } 153 | 154 | size() { 155 | return this.listSize; 156 | } 157 | 158 | print() { 159 | let current = this.head; 160 | let string = ''; 161 | let index = 0; 162 | 163 | while (current) { 164 | string += `[${index}]${current.element}${current.next ? '=>' : ''}`; 165 | current = current.next; 166 | index++; 167 | } 168 | 169 | return string; 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/data-structures/linked-lists/LinkedList.js: -------------------------------------------------------------------------------- 1 | export default class LinkedList { 2 | constructor() { 3 | this.head = null; 4 | this.listSize = 0; 5 | } 6 | 7 | Node(element) { 8 | return { 9 | element, 10 | next: null 11 | }; 12 | } 13 | 14 | append(element) { 15 | const node = this.Node(element); 16 | let current; 17 | 18 | // Si la lista esta vacia (Primer elemento) 19 | if (this.head === null) { 20 | this.head = node; 21 | } else { 22 | // Si ya tiene datos comenzamos a recorrer la lista desde head 23 | current = this.head; 24 | 25 | // Mientras exista un element en el node.next (cuando llegue a null sera el final de la lista) 26 | while (current.next) { 27 | // current tome el valor del proximo elemento (next) 28 | current = current.next; 29 | } 30 | 31 | // Ahora current ya tiene el último elemento y asignamos el nuevo elemento a su next 32 | current.next = node; 33 | } 34 | 35 | // Incrementamos el tamaño de la lista 36 | this.listSize++; 37 | } 38 | 39 | insert(position, element) { 40 | // Validar el rango 41 | if (position >= 0 && position <= this.listSize) { 42 | const node = this.Node(element); 43 | let current = this.head; 44 | let previous; 45 | let index = 0; 46 | 47 | // Agregar un elemento al inicio la lista 48 | if (position === 0) { 49 | node.next = current; 50 | this.head = node; 51 | } else { 52 | // Recorrer la lista hasta la posicion indicada 53 | while (index++ < posicion) { 54 | previous = current; 55 | current = current.next; 56 | } 57 | 58 | node.next = current; 59 | previous.next = node; 60 | } 61 | 62 | // Incrementamos el tamaño de la lista 63 | this.listSize++; 64 | 65 | return true; 66 | } 67 | 68 | return false; 69 | } 70 | 71 | removeAt(position) { 72 | // Validar el rango 73 | if (position > -1 && position < this.listSize) { 74 | let current = this.head; 75 | let previous; 76 | let index = 0; 77 | 78 | // Quitamos el primer elemento 79 | if (position === 0) { 80 | this.head = current.next; 81 | } else { 82 | // Recorremos la lista hasta la posicion indicada 83 | while (index++ < position) { 84 | previous = current; 85 | current = current.next; 86 | } 87 | 88 | // Enlazamos el elemento anterior con el next del current (saltamos el elemento para eliminarlo) 89 | previous.next = current.next; 90 | } 91 | 92 | this.listSize--; 93 | 94 | // Retornamos el elemento eliminado 95 | return current.element; 96 | } 97 | 98 | return false; 99 | } 100 | 101 | remove(element) { 102 | const index = this.indexOf(element); 103 | 104 | return this.removeAt(index); 105 | } 106 | 107 | indexOf(element) { 108 | let current = this.head; 109 | let index = 0; 110 | 111 | while (current) { 112 | if (current.element === element) { 113 | return index; 114 | } 115 | 116 | index++; 117 | current = current.next; 118 | } 119 | 120 | return -1; 121 | } 122 | 123 | hasElements() { 124 | return this.listSize > 0; 125 | } 126 | 127 | size() { 128 | return this.listSize; 129 | } 130 | 131 | print() { 132 | let current = this.head; 133 | let string = ''; 134 | let index = 0; 135 | 136 | while (current) { 137 | string += `[${index}]${current.element}${current.next ? '=>' : ''}`; 138 | current = current.next; 139 | index++; 140 | } 141 | 142 | return string; 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/data-structures/queues/HotPotato.js: -------------------------------------------------------------------------------- 1 | import Queue from './Queue'; 2 | 3 | export default function HotPotato(players, spins) { 4 | const queue = new Queue(); 5 | 6 | for (let i = 0; i < players.length; i++) { 7 | queue.enqueue(players[i]); 8 | } 9 | 10 | let eliminated = ''; 11 | 12 | while (queue.size() > 1) { 13 | for (let i = 0; i < spins; i++) { 14 | queue.enqueue(queue.dequeue()); 15 | } 16 | 17 | eliminated = queue.dequeue(); 18 | 19 | console.log(eliminated, 'fue eliminado de la papa caliente'); 20 | } 21 | 22 | return queue.dequeue(); 23 | } 24 | -------------------------------------------------------------------------------- /src/data-structures/queues/PriorityQueue.js: -------------------------------------------------------------------------------- 1 | export default function PriorityQueue() { 2 | let items = []; 3 | 4 | function QueueElement(element, priority) { 5 | this.element = element; 6 | this.priority = priority || 1; 7 | } 8 | 9 | this.enqueue = (element, priority) => { 10 | const queueElement = new QueueElement(element, priority); 11 | let added = false; 12 | 13 | for (let i = 0; i < items.length; i++) { 14 | if (queueElement.priority < items[i].priority) { 15 | items.splice(i, 0, queueElement); 16 | added = true; 17 | break; 18 | } 19 | } 20 | 21 | if (!added) { 22 | items.push(queueElement); 23 | } 24 | }; 25 | 26 | this.dequeue = () => { 27 | return items.shift(); 28 | }; 29 | 30 | this.front = () => { 31 | return items[0]; 32 | }; 33 | 34 | this.hasElements = () => { 35 | return items.length > 0; 36 | }; 37 | 38 | this.size = () => { 39 | return items.length; 40 | }; 41 | 42 | this.print = () => { 43 | let printStr = ''; 44 | let pipe = '|'; 45 | 46 | for (let i = 0; i < items.length; i++) { 47 | if (i === items.length - 1) { 48 | pipe = ''; 49 | } 50 | 51 | printStr += `${items[i].element}-${items[i].priority}${pipe}`; 52 | } 53 | 54 | return printStr; 55 | }; 56 | 57 | this.clear = () => { 58 | items = []; 59 | }; 60 | } 61 | -------------------------------------------------------------------------------- /src/data-structures/queues/Queue.js: -------------------------------------------------------------------------------- 1 | export default function Queue() { 2 | let items = []; 3 | 4 | this.enqueue = element => { 5 | items.push(element); 6 | }; 7 | 8 | this.dequeue = () => { 9 | return items.shift(); 10 | }; 11 | 12 | this.front = () => { 13 | return items[0]; 14 | }; 15 | 16 | this.hasElements = () => { 17 | return items.length > 0; 18 | }; 19 | 20 | this.size = () => { 21 | return items.length; 22 | }; 23 | 24 | this.print = () => { 25 | return items.toString(); 26 | }; 27 | 28 | this.clear = () => { 29 | items = []; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/data-structures/sets/Set.js: -------------------------------------------------------------------------------- 1 | export default function Set() { 2 | let items = {}; 3 | 4 | this.getItems = () => { 5 | return items; 6 | }; 7 | 8 | this.add = value => { 9 | if (!this.has(value)) { 10 | items[value] = value; 11 | 12 | return true; 13 | } 14 | 15 | return false; 16 | }; 17 | 18 | this.delete = value => { 19 | if (this.has(value)) { 20 | delete items[value]; 21 | 22 | return true; 23 | } 24 | 25 | return false; 26 | }; 27 | 28 | this.has = value => { 29 | return items.hasOwnProperty(value); 30 | }; 31 | 32 | this.clear = () => { 33 | items = {}; 34 | }; 35 | 36 | this.size = () => { 37 | return Object.keys(items).length; 38 | }; 39 | 40 | this.values = () => { 41 | const values = []; 42 | const keys = Object.keys(items); 43 | 44 | for (let i = 0; i < keys.length; i++) { 45 | values.push(items[keys[i]]); 46 | } 47 | 48 | return values; 49 | }; 50 | 51 | this.union = otherSet => { 52 | const unionSet = new Set(); 53 | let values = this.values(); 54 | 55 | for (let i = 0; i < values.length; i++) { 56 | unionSet.add(values[i]); 57 | } 58 | 59 | values = otherSet.values(); 60 | 61 | for (let i = 0; i < values.length; i++) { 62 | unionSet.add(values[i]); 63 | } 64 | 65 | return unionSet; 66 | }; 67 | 68 | this.intersection = otherSet => { 69 | const intersectionSet = new Set(); 70 | const values = this.values(); 71 | 72 | for (let i = 0; i < values.length; i++) { 73 | if (otherSet.has(values[i])) { 74 | intersectionSet.add(values[i]); 75 | } 76 | } 77 | 78 | return intersectionSet; 79 | }; 80 | 81 | this.difference = otherSet => { 82 | const differenceSet = new Set(); 83 | const values = this.values(); 84 | 85 | for (let i = 0; i < values.length; i++) { 86 | if (!otherSet.has(values[i])) { 87 | differenceSet.add(values[i]); 88 | } 89 | } 90 | 91 | return differenceSet; 92 | }; 93 | 94 | this.subset = otherSet => { 95 | if (this.size() > otherSet.size()) { 96 | return false; 97 | } else { 98 | const values = this.values(); 99 | 100 | for (let i = 0; i < values.length; i++) { 101 | if (!otherSet.has(values[i])) { 102 | return false; 103 | } 104 | } 105 | 106 | return true; 107 | } 108 | }; 109 | } 110 | -------------------------------------------------------------------------------- /src/data-structures/stacks/Dec2Bin.js: -------------------------------------------------------------------------------- 1 | import Stack from './Stack'; 2 | 3 | export default function dec2Bin(dNumber) { 4 | if (dNumber === 0) { 5 | return '0'; 6 | } 7 | 8 | const stack = new Stack(); 9 | let rem; 10 | let binaryString = ''; 11 | 12 | while (dNumber > 0) { 13 | // Remaining 14 | rem = Math.floor(dNumber % 2); 15 | 16 | // Pushing to the stack 17 | stack.push(rem); 18 | 19 | // Divide by 2 20 | dNumber = Math.floor(dNumber / 2); 21 | } 22 | 23 | // While the stack has elements 24 | while (stack.hasElements()) { 25 | // Concatenate each element. 26 | binaryString += stack.pop().toString(); 27 | } 28 | 29 | return binaryString; 30 | } 31 | -------------------------------------------------------------------------------- /src/data-structures/stacks/Stack.js: -------------------------------------------------------------------------------- 1 | export default function Stack() { 2 | let items = []; 3 | 4 | this.push = element => { 5 | items.push(element); 6 | }; 7 | 8 | this.pop = () => { 9 | return this.hasElements() ? items.pop() : false; 10 | }; 11 | 12 | this.last = () => { 13 | return items[items.length - 1]; 14 | }; 15 | 16 | this.hasElements = () => { 17 | return items.length > 0; 18 | }; 19 | 20 | this.size = () => { 21 | return items.length; 22 | }; 23 | 24 | this.print = () => { 25 | return items.toString(); 26 | }; 27 | 28 | this.clear = () => { 29 | items = []; 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/interview-questions/arrays/flatten.js: -------------------------------------------------------------------------------- 1 | /* 2 | Write a function that deeply flatten an array 3 | */ 4 | 5 | const array = [1, [2, [[3, 4], 5], 6]]; 6 | 7 | function flatten(array) { 8 | return array.reduce((acc, value) => { 9 | return acc.concat(value instanceof Array ? flatten(value) : value); 10 | }, []); 11 | } 12 | 13 | console.log(flatten(array)); 14 | -------------------------------------------------------------------------------- /src/interview-questions/arrays/question1.js: -------------------------------------------------------------------------------- 1 | /* 2 | We have an array of objects A and an array of indexes B. 3 | Reorder objects in array A with given indexes in array B. Do not change array A's length. 4 | 5 | Example: 6 | let a = [C, D, E, F, G]; 7 | let b = [3, 0, 4, 1, 2]; 8 | 9 | sort(a, b); 10 | // a is now [D, F, G, C, E]; 11 | // b is now [0, 1, 2, 3, 4] 12 | */ 13 | 14 | function swap(array, indexA, indexB) { 15 | const tmp = array[indexA]; 16 | array[indexA] = array[indexB]; 17 | array[indexB] = tmp; 18 | 19 | return array; 20 | } 21 | 22 | function sort(a, b) { 23 | for (let i = 0; i < b.length; i++) { 24 | if (i !== b[i]) { 25 | a = swap(a, i, b[i]); 26 | b = swap(b, i, b[i]); 27 | } 28 | } 29 | 30 | return a; 31 | } 32 | 33 | sort(['C', 'D', 'E', 'F', 'G'], [3, 0, 4, 1, 2]); 34 | -------------------------------------------------------------------------------- /src/interview-questions/arrays/reordering.js: -------------------------------------------------------------------------------- 1 | /* 2 | Given an input array and another array that describes a new 3 | index for each element, mutate the input array so that each element ends up 4 | in their new index. Discuss the runtime of the algorithm and how you can be 5 | sure there won't be any infinite loops. 6 | */ 7 | 8 | let array = ['A', 'B', 'C', 'D', 'E', 'F']; 9 | const indices = [2, 3, 4, 0, 5, 1]; 10 | 11 | array = indices.map((value, index) => { 12 | return array[indices.indexOf(index)]; 13 | }); 14 | 15 | // returns: ["D", "F", "A", "B", "C", "E"] 16 | -------------------------------------------------------------------------------- /src/interview-questions/dom/nodeX.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | NodeX 5 | 6 | 7 | 8 |
9 |
10 |
11 |
12 | 13 |
14 |
15 |
16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 |
28 |
29 | 30 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/interview-questions/events/debounce.js: -------------------------------------------------------------------------------- 1 | // Returns a function, that, as long as it continues to be invoked, will not 2 | // be triggered. The function will be called after it stops being called for 3 | // N milliseconds. If `immediate` is passed, trigger the function on the 4 | // leading edge, instead of the trailing. 5 | 6 | function debounce(fn, wait, immediate) { 7 | let timeout; 8 | 9 | return () => { 10 | const args = arguments; 11 | const later = () => { 12 | timeout = null; 13 | 14 | if (!immediate) { 15 | fn.apply(null, args); 16 | } 17 | }; 18 | 19 | const callNow = immediate && !timeout; 20 | 21 | clearTimeout(timeout); 22 | 23 | timeout = setTimeout(later, wait); 24 | 25 | if (callNow) { 26 | fn.apply(null, args); 27 | } 28 | }; 29 | } 30 | 31 | const myEfficientFn = debounce(() => { 32 | // All the taxing stuff you do 33 | }, 200); 34 | 35 | window.addEventListener('scroll', myEfficientFn); 36 | -------------------------------------------------------------------------------- /src/interview-questions/events/emitter.js: -------------------------------------------------------------------------------- 1 | class EventEmitter { 2 | constructor() { 3 | this.events = {}; 4 | } 5 | 6 | emit(eventName, data) { 7 | const event = this.events[eventName]; 8 | 9 | if (event) { 10 | event.forEach(fn => { 11 | fn.call(null, data); 12 | }); 13 | } 14 | } 15 | 16 | subscribe(eventName, fn) { 17 | if (!this.events[eventName]) { 18 | this.events[eventName] = []; 19 | } 20 | 21 | this.events[eventName].push(fn); 22 | } 23 | 24 | unsubscribe(eventName) { 25 | if (this.events[eventName]) { 26 | delete this.events[eventName]; 27 | } 28 | } 29 | } 30 | 31 | document.addEventListener('DOMContentLoaded', event => { 32 | const input = document.querySelector('input[type="text"]'); 33 | const button = document.querySelector('button'); 34 | const h1 = document.querySelector('h1'); 35 | const emitter = new EventEmitter(); 36 | 37 | emitter.subscribe('event:name-changed', data => { 38 | h1.innerHTML = `Your name is: ${data.name}`; 39 | }); 40 | 41 | emitter.subscribe('event:name-changed', data => { 42 | console.log(`Your name 2 is: ${data.name}`); 43 | }); 44 | 45 | // emitter.unsubscribe('event:name-changed'); 46 | 47 | button.addEventListener('click', () => { 48 | emitter.emit('event:name-changed', { 49 | name: input.value 50 | }); 51 | }); 52 | }); 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/interview-questions/events/taxing.js: -------------------------------------------------------------------------------- 1 | /* 2 | If you were building a search tool and wanted search 3 | results to pop up as you typed but the server call was taxing, 4 | write a function that gets called on every key down but calls the server 5 | when the user stops typing for 400ms. 6 | */ 7 | 8 | const searchField = document.getElementById('searchField'); 9 | let lastTimeId; 10 | 11 | searchField.addEventListener('keydown', (e) => { 12 | if (typeof lastTimeId !== 'undefined') { 13 | clearTimeout(lastTimeId); 14 | } 15 | 16 | lastTimeId = setTimeout(() => { 17 | // Do search stuff 18 | console.log(`Do search for ${searchField.value}`); 19 | }, 400); 20 | }); 21 | -------------------------------------------------------------------------------- /src/interview-questions/html-css/edit-icon.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | Parent 8 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/interview-questions/html-css/parent.html: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | Parent 8 | 26 | 27 | 28 |
29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/data-structures/dictionaries/dictionaryTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import Dictionary from '../../../src/data-structures/dictionaries/Dictionary'; 3 | 4 | const dictionary = new Dictionary(); 5 | 6 | describe('@Dictionary', () => { 7 | describe('#set', () => { 8 | it('should be a function', () => { 9 | assert.typeOf(dictionary.set, 'function', 'set should be a function'); 10 | }); 11 | 12 | it('should set new element(s)', () => { 13 | dictionary.set('Carlos', 'carlos@gmail.com'); 14 | dictionary.set('Cristina', 'cristina@gmail.com'); 15 | dictionary.set('Javier', 'javier@gmail.com'); 16 | 17 | console.log(cyan, 'Current Dictionary ========> ', green, dictionary.getItems()); 18 | 19 | // The set should have 3 elements (length) 20 | const actualResult = dictionary.size(); 21 | const expectedResult = 3; 22 | 23 | assert.isTrue(expectedResult === actualResult); 24 | }); 25 | }); 26 | 27 | describe('#delete', () => { 28 | it('should be a function', () => { 29 | assert.typeOf(dictionary.delete, 'function', 'delete should be a function'); 30 | }); 31 | 32 | it('should delete an element', () => { 33 | const actualResult = dictionary.delete('Cristina'); 34 | const expectedResult = true; 35 | 36 | console.log(cyan, 'Current Dictionary ========> ', green, dictionary.getItems()); 37 | 38 | assert.isTrue(expectedResult === actualResult); 39 | }); 40 | }); 41 | 42 | describe('#has', () => { 43 | it('should be a function', () => { 44 | assert.typeOf(dictionary.has, 'function', 'has should be a function'); 45 | }); 46 | 47 | it('should validate if a set has an element', () => { 48 | // Getting the first element 49 | const actualResult = dictionary.has('Carlos'); 50 | const expectedResult = true; 51 | 52 | assert.isTrue(expectedResult === actualResult); 53 | }); 54 | }); 55 | 56 | describe('#size', () => { 57 | it('should be a function', () => { 58 | assert.typeOf(dictionary.size, 'function', 'size should be a function'); 59 | }); 60 | 61 | it('should return the current size of the queue', () => { 62 | // Getting the size of the actual list 63 | const actualResult = dictionary.size(); 64 | const expectedResult = 2; 65 | 66 | assert.isTrue(expectedResult === actualResult); 67 | }); 68 | }); 69 | 70 | describe('#get', () => { 71 | it('should be a function', () => { 72 | assert.typeOf(dictionary.get, 'function', 'get should be a function'); 73 | }); 74 | 75 | it('should return the selected element', () => { 76 | const actualResult = dictionary.get('Javier'); 77 | const expectedResult = 'javier@gmail.com'; 78 | 79 | console.log(cyan, 'Get ========> ', green, actualResult); 80 | 81 | assert.isTrue(expectedResult === actualResult); 82 | }); 83 | }); 84 | 85 | describe('#values', () => { 86 | it('should be a function', () => { 87 | assert.typeOf(dictionary.values, 'function', 'values should be a function'); 88 | }); 89 | 90 | it('should return the current values in array', () => { 91 | const actualResult = dictionary.values(); 92 | const expectedResult = ['carlos@gmail.com', 'javier@gmail.com']; 93 | 94 | console.log(cyan, 'Values ========> ', green, actualResult); 95 | 96 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 97 | }); 98 | }); 99 | 100 | describe('#keys', () => { 101 | it('should be a function', () => { 102 | assert.typeOf(dictionary.keys, 'function', 'keys should be a function'); 103 | }); 104 | 105 | it('should return the current keys in array', () => { 106 | const actualResult = dictionary.keys(); 107 | const expectedResult = ['Carlos', 'Javier']; 108 | 109 | console.log(cyan, 'Keys ========> ', green, actualResult); 110 | 111 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 112 | }); 113 | }); 114 | 115 | describe('#clear', () => { 116 | it('should be a function', () => { 117 | assert.typeOf(dictionary.clear, 'function', 'clear should be a function'); 118 | }); 119 | 120 | it('should clear the dictionary', () => { 121 | dictionary.clear(); 122 | 123 | const actualResult = dictionary.size(); 124 | const expectedResult = 0; 125 | 126 | assert.isTrue(expectedResult === actualResult); 127 | }); 128 | }); 129 | }); 130 | -------------------------------------------------------------------------------- /test/data-structures/linked-lists/doublyLinkedListTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import DoublyLinkedList from '../../../src/data-structures/linked-Lists/DoublyLinkedList'; 3 | 4 | const List = new DoublyLinkedList(); 5 | 6 | describe('@DoublyLinkedList', () => { 7 | describe('#append', () => { 8 | it('should be a function', () => { 9 | assert.typeOf(List.append, 'function', 'append should be a function'); 10 | }); 11 | 12 | it('should add new element(s)', () => { 13 | List.append(15); 14 | List.append(10); 15 | List.append(13); 16 | List.append(11); 17 | List.append(12); 18 | 19 | console.log(cyan, 'Current List ========> ', green, List.print()); 20 | 21 | // The queue should have 5 elements (length) 22 | const actualResult = List.size(); 23 | const expectedResult = 5; 24 | 25 | assert.isTrue(expectedResult === actualResult); 26 | }); 27 | }); 28 | 29 | describe('#insert', () => { 30 | it('should be a function', () => { 31 | assert.typeOf(List.insert, 'function', 'insert should be a function'); 32 | }); 33 | 34 | it('should insert at the beginning of the list', () => { 35 | // Inserting in position 0 36 | List.insert(0, 20); 37 | 38 | const actualResult = List.indexOf(20); 39 | const expectedResult = 0; 40 | 41 | console.log(cyan, 'Current List ========> ', green, List.print()); 42 | 43 | assert.isTrue(expectedResult === actualResult); 44 | }); 45 | }); 46 | 47 | describe('#removeAt', () => { 48 | it('should be a function', () => { 49 | assert.typeOf(List.removeAt, 'function', 'removeAt should be a function'); 50 | }); 51 | 52 | it('should remove the element in position 4', () => { 53 | // Getting the first element 54 | const actualResult = List.removeAt(4); 55 | const expectedResult = 11; 56 | 57 | console.log(cyan, 'Current List ========> ', red, List.print()); 58 | 59 | assert.isTrue(expectedResult === actualResult); 60 | }); 61 | }); 62 | 63 | describe('#remove', () => { 64 | it('should be a function', () => { 65 | assert.typeOf(List.remove, 'function', 'remove should be a function'); 66 | }); 67 | 68 | it('should remove a specific element', () => { 69 | // The queue has elements? 70 | const actualResult = List.remove(10); 71 | const expectedResult = 10; 72 | 73 | console.log(cyan, 'Current List ========> ', red, List.print()); 74 | 75 | assert.isTrue(expectedResult === actualResult); 76 | }); 77 | }); 78 | 79 | describe('#indexOf', () => { 80 | it('should be a function', () => { 81 | assert.typeOf(List.indexOf, 'function', 'indexOf should be a function'); 82 | }); 83 | 84 | it('should return the position of the element', () => { 85 | // Getting the size of the actual queue 86 | const actualResult = List.indexOf(12); 87 | const expectedResult = 3; 88 | 89 | assert.isTrue(expectedResult === actualResult); 90 | }); 91 | }); 92 | 93 | describe('#hasElements', () => { 94 | it('should be a function', () => { 95 | assert.typeOf(List.hasElements, 'function', 'hasElements should be a function'); 96 | }); 97 | 98 | it('should return true if the list has elements', () => { 99 | const actualResult = List.hasElements(); 100 | const expectedResult = true; 101 | 102 | assert.isTrue(expectedResult === actualResult); 103 | }); 104 | }); 105 | 106 | describe('#size', () => { 107 | it('should be a function', () => { 108 | assert.typeOf(List.size, 'function', 'size should be a function'); 109 | }); 110 | 111 | it('should return the current size of the queue', () => { 112 | // Getting the size of the actual list 113 | const actualResult = List.size(); 114 | const expectedResult = 4; 115 | 116 | assert.isTrue(expectedResult === actualResult); 117 | }); 118 | }); 119 | 120 | describe('#print', () => { 121 | it('should be a function', () => { 122 | assert.typeOf(List.print, 'function', 'print should be a function'); 123 | }); 124 | 125 | it('should print the current list', () => { 126 | const actualResult = List.print(); 127 | const expectedResult = '[0]20=>[1]15=>[2]13=>[3]12'; 128 | 129 | assert.isTrue(expectedResult === actualResult); 130 | }); 131 | }); 132 | }); 133 | -------------------------------------------------------------------------------- /test/data-structures/linked-lists/linkedListTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import LinkedList from '../../../src/data-structures/linked-Lists/LinkedList'; 3 | 4 | const List = new LinkedList(); 5 | 6 | describe('@LinkedList', () => { 7 | describe('#append', () => { 8 | it('should be a function', () => { 9 | assert.typeOf(List.append, 'function', 'append should be a function'); 10 | }); 11 | 12 | it('should add new element(s)', () => { 13 | List.append(15); 14 | List.append(10); 15 | List.append(13); 16 | List.append(11); 17 | List.append(12); 18 | 19 | console.log(cyan, 'Current List ========> ', green, List.print()); 20 | 21 | // The queue should have 5 elements (length) 22 | const actualResult = List.size(); 23 | const expectedResult = 5; 24 | 25 | assert.isTrue(expectedResult === actualResult); 26 | }); 27 | }); 28 | 29 | describe('#insert', () => { 30 | it('should be a function', () => { 31 | assert.typeOf(List.insert, 'function', 'insert should be a function'); 32 | }); 33 | 34 | it('should insert at the beginning of the list', () => { 35 | // Inserting in position 0 36 | List.insert(0, 20); 37 | 38 | const actualResult = List.indexOf(20); 39 | const expectedResult = 0; 40 | 41 | console.log(cyan, 'Current List ========> ', green, List.print()); 42 | 43 | assert.isTrue(expectedResult === actualResult); 44 | }); 45 | }); 46 | 47 | describe('#removeAt', () => { 48 | it('should be a function', () => { 49 | assert.typeOf(List.removeAt, 'function', 'removeAt should be a function'); 50 | }); 51 | 52 | it('should remove the element in position 4', () => { 53 | // Getting the first element 54 | const actualResult = List.removeAt(4); 55 | const expectedResult = 11; 56 | 57 | console.log(cyan, 'Current List ========> ', red, List.print()); 58 | 59 | assert.isTrue(expectedResult === actualResult); 60 | }); 61 | }); 62 | 63 | describe('#remove', () => { 64 | it('should be a function', () => { 65 | assert.typeOf(List.remove, 'function', 'remove should be a function'); 66 | }); 67 | 68 | it('should remove a specific element', () => { 69 | // The queue has elements? 70 | const actualResult = List.remove(10); 71 | const expectedResult = 10; 72 | 73 | console.log(cyan, 'Current List ========> ', red, List.print()); 74 | 75 | assert.isTrue(expectedResult === actualResult); 76 | }); 77 | }); 78 | 79 | describe('#indexOf', () => { 80 | it('should be a function', () => { 81 | assert.typeOf(List.indexOf, 'function', 'indexOf should be a function'); 82 | }); 83 | 84 | it('should return the position of the element', () => { 85 | // Getting the size of the actual queue 86 | const actualResult = List.indexOf(12); 87 | const expectedResult = 3; 88 | 89 | assert.isTrue(expectedResult === actualResult); 90 | }); 91 | }); 92 | 93 | describe('#hasElements', () => { 94 | it('should be a function', () => { 95 | assert.typeOf(List.hasElements, 'function', 'hasElements should be a function'); 96 | }); 97 | 98 | it('should return true if the list has elements', () => { 99 | const actualResult = List.hasElements(); 100 | const expectedResult = true; 101 | 102 | assert.isTrue(expectedResult === actualResult); 103 | }); 104 | }); 105 | 106 | describe('#size', () => { 107 | it('should be a function', () => { 108 | assert.typeOf(List.size, 'function', 'size should be a function'); 109 | }); 110 | 111 | it('should return the current size of the queue', () => { 112 | // Getting the size of the actual list 113 | const actualResult = List.size(); 114 | const expectedResult = 4; 115 | 116 | assert.isTrue(expectedResult === actualResult); 117 | }); 118 | }); 119 | 120 | describe('#print', () => { 121 | it('should be a function', () => { 122 | assert.typeOf(List.print, 'function', 'print should be a function'); 123 | }); 124 | 125 | it('should print the current list', () => { 126 | const actualResult = List.print(); 127 | const expectedResult = '[0]20=>[1]15=>[2]13=>[3]12'; 128 | 129 | assert.isTrue(expectedResult === actualResult); 130 | }); 131 | }); 132 | }); 133 | -------------------------------------------------------------------------------- /test/data-structures/queues/hotPotatoTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import HotPotato from '../../../src/data-structures/queues/HotPotato'; 3 | 4 | describe('@HotPotato', () => { 5 | describe('#HotPotato', () => { 6 | it('should be a function', () => { 7 | assert.typeOf(HotPotato, 'function', 'HotPotato should be a function'); 8 | }); 9 | 10 | it('should get a winner from the hot potato game', () => { 11 | // HotPotato Players 12 | const players = ['Carlos', 'Cristina', 'Javier', 'Jona', 'Sam']; 13 | 14 | // The winner is... 15 | const actualResult = HotPotato(players, 7); 16 | const expectedResult = 'Carlos'; 17 | 18 | assert.isTrue(expectedResult === actualResult); 19 | }); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /test/data-structures/queues/priorityQueueTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import PriorityQueue from '../../../src/data-structures/queues/PriorityQueue'; 3 | 4 | const { 5 | enqueue, 6 | dequeue, 7 | front, 8 | hasElements, 9 | size, 10 | clear, 11 | print 12 | } = new PriorityQueue(); 13 | 14 | describe('@PriorityQueue', () => { 15 | describe('#enqueue', () => { 16 | it('should be a function', () => { 17 | assert.typeOf(enqueue, 'function', 'enqueue should be a function'); 18 | }); 19 | 20 | it('should add new element(s) with priority', () => { 21 | // Adding new people 22 | enqueue('Carlos', 3); // [2] 23 | enqueue('Cristina', 1); // [0] 24 | enqueue('Jona', 5); // [4] 25 | enqueue('Javier', 2); // [1] 26 | enqueue('Sam', 4); // [3] 27 | 28 | /* 29 | [ 30 | QueueElement { element: 'Cristina', priority: 1 }, [0] 31 | QueueElement { element: 'Javier', priority: 2 }, [1] 32 | QueueElement { element: 'Carlos', priority: 3 }, [2] 33 | QueueElement { element: 'Sam', priority: 4 }, [3] 34 | QueueElement { element: 'Jona', priority: 5 } [4] 35 | ] 36 | */ 37 | 38 | // The queue should have 5 elements (length) 39 | const actualResult = size(); 40 | const expectedResult = 5; 41 | 42 | assert.isTrue(expectedResult === actualResult); 43 | }); 44 | }); 45 | 46 | describe('#dequeue', () => { 47 | it('should be a function', () => { 48 | assert.typeOf(dequeue, 'function', 'dequeue should be a function'); 49 | }); 50 | 51 | it('should remove and return the first element', () => { 52 | // Removing the first element 53 | const actualResult = dequeue(); 54 | const expectedResult = { 55 | element: 'Cristina', 56 | priority: 1 57 | }; 58 | 59 | assert.isTrue(size() === 4); // The size now should be 4 60 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 61 | }); 62 | }); 63 | 64 | describe('#front', () => { 65 | it('should be a function', () => { 66 | assert.typeOf(front, 'function', 'front should be a function'); 67 | }); 68 | 69 | it('should return the first element', () => { 70 | // Getting the first element 71 | const actualResult = front(); 72 | const expectedResult = { 73 | element: 'Javier', 74 | priority: 2 75 | }; 76 | 77 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 78 | }); 79 | }); 80 | 81 | describe('#hasElements', () => { 82 | it('should be a function', () => { 83 | assert.typeOf(hasElements, 'function', 'hasElements should be a function'); 84 | }); 85 | 86 | it('should return true if the queue has elements', () => { 87 | // The queue has elements? 88 | const actualResult = hasElements(); 89 | const expectedResult = true; 90 | 91 | assert.isTrue(expectedResult === actualResult); // The queue has elements! 92 | }); 93 | }); 94 | 95 | describe('#size', () => { 96 | it('should be a function', () => { 97 | assert.typeOf(size, 'function', 'size should be a function'); 98 | }); 99 | 100 | it('should return the current size of the queue', () => { 101 | // Getting the size of the actual queue 102 | const actualResult = size(); 103 | const expectedResult = 4; 104 | 105 | assert.isTrue(expectedResult === actualResult); // The queue has 4 elements! 106 | }); 107 | }); 108 | 109 | describe('#clear', () => { 110 | it('should be a function', () => { 111 | assert.typeOf(clear, 'function', 'clear should be a function'); 112 | }); 113 | 114 | it('should clear the queue', () => { 115 | // Clear queue 116 | clear(); 117 | 118 | const actualResult = size(); 119 | const expectedResult = 0; 120 | 121 | assert.isTrue(expectedResult === actualResult); // The queue has 0 elements! 122 | }); 123 | }); 124 | 125 | describe('#print', () => { 126 | it('should be a function', () => { 127 | assert.typeOf(print, 'function', 'print should be a function'); 128 | }); 129 | 130 | it('should print the current queue', () => { 131 | // Adding new elements 132 | enqueue(10, 2); 133 | enqueue(20); 134 | enqueue(30); 135 | 136 | const actualResult = print(); 137 | const expectedResult = '20-1|30-1|10-2'; 138 | 139 | assert.isTrue(expectedResult === actualResult); // The new queue is [10, 20, 30] 140 | }); 141 | }); 142 | }); 143 | -------------------------------------------------------------------------------- /test/data-structures/queues/queueTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import Queue from '../../../src/data-structures/queues/Queue'; 3 | 4 | const { 5 | enqueue, 6 | dequeue, 7 | front, 8 | hasElements, 9 | size, 10 | clear, 11 | print 12 | } = new Queue(); 13 | 14 | describe('@Queue', () => { 15 | describe('#enqueue', () => { 16 | it('should be a function', () => { 17 | assert.typeOf(enqueue, 'function', 'enqueue should be a function'); 18 | }); 19 | 20 | it('should add new element(s)', () => { 21 | // Adding new people 22 | enqueue('Carlos'); // [0] 23 | enqueue('Cristina'); // [1] 24 | enqueue('Javier'); // [2] 25 | enqueue('Jona'); // [3] 26 | enqueue('Sam'); // [4] 27 | 28 | // The queue should have 5 elements (length) 29 | const actualResult = size(); 30 | const expectedResult = 5; 31 | 32 | assert.isTrue(expectedResult === actualResult); 33 | }); 34 | }); 35 | 36 | describe('#dequeue', () => { 37 | it('should be a function', () => { 38 | assert.typeOf(dequeue, 'function', 'dequeue should be a function'); 39 | }); 40 | 41 | it('should remove and return the first element', () => { 42 | // Removing the first element 43 | const actualResult = dequeue(); 44 | const expectedResult = 'Carlos'; 45 | 46 | assert.isTrue(size() === 4); // The size now should be 4 47 | assert.isTrue(expectedResult === actualResult); // The first element removed is 'Carlos' 48 | }); 49 | }); 50 | 51 | describe('#front', () => { 52 | it('should be a function', () => { 53 | assert.typeOf(front, 'function', 'front should be a function'); 54 | }); 55 | 56 | it('should return the first element', () => { 57 | // Getting the first element 58 | const actualResult = front(); 59 | const expectedResult = 'Cristina'; 60 | 61 | assert.isTrue(expectedResult === actualResult); // The first element is 'Cristina' 62 | }); 63 | }); 64 | 65 | describe('#hasElements', () => { 66 | it('should be a function', () => { 67 | assert.typeOf(hasElements, 'function', 'hasElements should be a function'); 68 | }); 69 | 70 | it('should return true if the queue has elements', () => { 71 | // The queue has elements? 72 | const actualResult = hasElements(); 73 | const expectedResult = true; 74 | 75 | assert.isTrue(expectedResult === actualResult); // The queue has elements! 76 | }); 77 | }); 78 | 79 | describe('#size', () => { 80 | it('should be a function', () => { 81 | assert.typeOf(size, 'function', 'size should be a function'); 82 | }); 83 | 84 | it('should return the current size of the queue', () => { 85 | // Getting the size of the actual queue 86 | const actualResult = size(); 87 | const expectedResult = 4; 88 | 89 | assert.isTrue(expectedResult === actualResult); // The queue has 4 elements! 90 | }); 91 | }); 92 | 93 | describe('#clear', () => { 94 | it('should be a function', () => { 95 | assert.typeOf(clear, 'function', 'clear should be a function'); 96 | }); 97 | 98 | it('should clear the queue', () => { 99 | // Clear queue 100 | clear(); 101 | 102 | const actualResult = size(); 103 | const expectedResult = 0; 104 | 105 | assert.isTrue(expectedResult === actualResult); // The queue has 0 elements! 106 | }); 107 | }); 108 | 109 | describe('#print', () => { 110 | it('should be a function', () => { 111 | assert.typeOf(print, 'function', 'print should be a function'); 112 | }); 113 | 114 | it('should print the current queue', () => { 115 | // Adding new elements 116 | enqueue(10); 117 | enqueue(20); 118 | enqueue(30); 119 | 120 | const actualResult = print(); 121 | const expectedResult = '10,20,30'; 122 | 123 | assert.isTrue(expectedResult === actualResult); // The new queue is [10, 20, 30] 124 | }); 125 | }); 126 | }); 127 | -------------------------------------------------------------------------------- /test/data-structures/sets/setTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import Set from '../../../src/data-structures/sets/Set'; 3 | 4 | const set = new Set(); 5 | 6 | describe('@Set', () => { 7 | describe('#add', () => { 8 | it('should be a function', () => { 9 | assert.typeOf(set.add, 'function', 'add should be a function'); 10 | }); 11 | 12 | it('should add new element(s)', () => { 13 | set.add(1); 14 | set.add(2); 15 | set.add(3); 16 | set.add(4); 17 | set.add(5); 18 | 19 | console.log(cyan, 'Current Set ========> ', green, set.getItems()); 20 | 21 | // The set should have 5 elements (length) 22 | const actualResult = set.size(); 23 | const expectedResult = 5; 24 | 25 | assert.isTrue(expectedResult === actualResult); 26 | }); 27 | }); 28 | 29 | describe('#delete', () => { 30 | it('should be a function', () => { 31 | assert.typeOf(set.delete, 'function', 'delete should be a function'); 32 | }); 33 | 34 | it('should delete an element', () => { 35 | const actualResult = set.delete(4); 36 | const expectedResult = true; 37 | 38 | console.log(cyan, 'Current Set ========> ', green, set.getItems()); 39 | 40 | assert.isTrue(expectedResult === actualResult); 41 | }); 42 | }); 43 | 44 | describe('#has', () => { 45 | it('should be a function', () => { 46 | assert.typeOf(set.has, 'function', 'has should be a function'); 47 | }); 48 | 49 | it('should validate if a set has an element', () => { 50 | // Getting the first element 51 | const actualResult = set.has(2); 52 | const expectedResult = true; 53 | 54 | assert.isTrue(expectedResult === actualResult); 55 | }); 56 | }); 57 | 58 | describe('#size', () => { 59 | it('should be a function', () => { 60 | assert.typeOf(set.size, 'function', 'size should be a function'); 61 | }); 62 | 63 | it('should return the current size of the queue', () => { 64 | // Getting the size of the actual list 65 | const actualResult = set.size(); 66 | const expectedResult = 4; 67 | 68 | assert.isTrue(expectedResult === actualResult); 69 | }); 70 | }); 71 | 72 | describe('#values', () => { 73 | it('should be a function', () => { 74 | assert.typeOf(set.values, 'function', 'values should be a function'); 75 | }); 76 | 77 | it('should return the current values in array', () => { 78 | const actualResult = set.values(); 79 | const expectedResult = [1, 2, 3, 5]; 80 | 81 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 82 | }); 83 | }); 84 | 85 | describe('#clear', () => { 86 | it('should be a function', () => { 87 | assert.typeOf(set.clear, 'function', 'clear should be a function'); 88 | }); 89 | 90 | it('should clear the set', () => { 91 | set.clear(); 92 | 93 | const actualResult = set.size(); 94 | const expectedResult = 0; 95 | 96 | assert.isTrue(expectedResult === actualResult); 97 | }); 98 | }); 99 | 100 | describe('#union', () => { 101 | it('should be a function', () => { 102 | assert.typeOf(set.union, 'function', 'union should be a function'); 103 | }); 104 | 105 | it('should return the union of two sets', () => { 106 | const setA = new Set(); 107 | 108 | setA.add(1); 109 | setA.add(2); 110 | setA.add(3); 111 | 112 | const setB = new Set(); 113 | 114 | setB.add(4); 115 | setB.add(5); 116 | setB.add(6); 117 | 118 | const unionAB = setA.union(setB); 119 | 120 | console.log(cyan, 'Current Set ========> ', green, unionAB.getItems()); 121 | 122 | // The union set should have [1, 2, 3, 4, 5, 6] 123 | const actualResult = unionAB.values(); 124 | const expectedResult = [1, 2, 3, 4, 5, 6]; 125 | 126 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 127 | }); 128 | }); 129 | 130 | describe('#intersection', () => { 131 | it('should be a function', () => { 132 | assert.typeOf(set.union, 'function', 'intersection should be a function'); 133 | }); 134 | 135 | it('should return the intersection of two sets', () => { 136 | const setA = new Set(); 137 | 138 | setA.add(1); 139 | setA.add(2); 140 | setA.add(3); 141 | 142 | const setB = new Set(); 143 | 144 | setB.add(2); 145 | setB.add(3); 146 | setB.add(4); 147 | 148 | const intersectionAB = setA.intersection(setB); 149 | 150 | console.log(cyan, 'Current Set ========> ', green, intersectionAB.getItems()); 151 | 152 | // The intersection set should have [2, 3] 153 | const actualResult = intersectionAB.values(); 154 | const expectedResult = [2, 3]; 155 | 156 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 157 | }); 158 | }); 159 | 160 | describe('#difference', () => { 161 | it('should be a function', () => { 162 | assert.typeOf(set.union, 'function', 'difference should be a function'); 163 | }); 164 | 165 | it('should return the difference of two sets', () => { 166 | const setA = new Set(); 167 | 168 | setA.add(1); 169 | setA.add(2); 170 | setA.add(3); 171 | 172 | const setB = new Set(); 173 | 174 | setB.add(2); 175 | setB.add(3); 176 | setB.add(4); 177 | 178 | const differenceAB = setA.difference(setB); 179 | 180 | console.log(cyan, 'Current Set ========> ', green, differenceAB.getItems()); 181 | 182 | // The difference set should have [1] 183 | const actualResult = differenceAB.values(); 184 | const expectedResult = [1]; 185 | 186 | assert.deepEqual(expectedResult, actualResult, 'expectedResult should match actualResult'); 187 | }); 188 | }); 189 | 190 | describe('#subset', () => { 191 | it('should be a function', () => { 192 | assert.typeOf(set.union, 'function', 'subset should be a function'); 193 | }); 194 | 195 | it('should return the subset of two sets', () => { 196 | const setA = new Set(); 197 | 198 | setA.add(1); 199 | setA.add(2); 200 | 201 | const setB = new Set(); 202 | 203 | setB.add(1); 204 | setB.add(2); 205 | setB.add(3); 206 | 207 | const setC = new Set(); 208 | 209 | setB.add(2); 210 | setB.add(3); 211 | setB.add(4); 212 | 213 | assert.isTrue(setA.subset(setB)); // Set A is subset of Set B (contains both values) 214 | assert.isFalse(setA.subset(setC)); // Set A is not subset of Set C (just contains 2) 215 | }); 216 | }); 217 | }); 218 | -------------------------------------------------------------------------------- /test/data-structures/stacks/dec2BinTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import dec2Bin from '../../../src/data-structures/stacks/dec2Bin'; 3 | 4 | describe('@Dec2Bin', () => { 5 | describe('#dec2Bin', () => { 6 | it('should be a function', () => { 7 | assert.typeOf(dec2Bin, 'function', 'dec2Bin should be a function'); 8 | }); 9 | 10 | it('should convert decimal number to binary', () => { 11 | assert.isTrue(dec2Bin(0) === '0'); 12 | assert.isTrue(dec2Bin(1) === '1'); 13 | assert.isTrue(dec2Bin(2) === '10'); 14 | assert.isTrue(dec2Bin(3) === '11'); 15 | assert.isTrue(dec2Bin(4) === '100'); 16 | assert.isTrue(dec2Bin(5) === '101'); 17 | assert.isTrue(dec2Bin(6) === '110'); 18 | assert.isTrue(dec2Bin(7) === '111'); 19 | assert.isTrue(dec2Bin(8) === '1000'); 20 | assert.isTrue(dec2Bin(9) === '1001'); 21 | assert.isTrue(dec2Bin(10) === '1010'); 22 | assert.isTrue(dec2Bin(11) === '1011'); 23 | assert.isTrue(dec2Bin(12) === '1100'); 24 | assert.isTrue(dec2Bin(13) === '1101'); 25 | assert.isTrue(dec2Bin(14) === '1110'); 26 | assert.isTrue(dec2Bin(15) === '1111'); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/data-structures/stacks/stackTest.js: -------------------------------------------------------------------------------- 1 | import '../../globalTest'; 2 | import Stack from '../../../src/data-structures/stacks/Stack'; 3 | 4 | const { 5 | push, 6 | pop, 7 | last, 8 | hasElements, 9 | size, 10 | clear, 11 | print 12 | } = new Stack(); 13 | 14 | describe('@Stack', () => { 15 | describe('#push', () => { 16 | it('should be a function', () => { 17 | assert.typeOf(push, 'function', 'push should be a function'); 18 | }); 19 | 20 | it('should add new element(s)', () => { 21 | // Adding new books to the stack 22 | push('El Señor de los Anillos'); // [0] 23 | push('El Código da Vinci'); // [1] 24 | push('Kain y Abel'); // [2] 25 | push('El Alquimista'); // [3] 26 | push('El Hobbit'); // [4] 27 | 28 | // The stack should have 5 elements (length) 29 | const actualResult = size(); 30 | const expectedResult = 5; 31 | 32 | assert.isTrue(expectedResult === actualResult); 33 | }); 34 | }); 35 | 36 | describe('#pop', () => { 37 | it('should be a function', () => { 38 | assert.typeOf(pop, 'function', 'pop should be a function'); 39 | }); 40 | 41 | it('should remove and return the last element', () => { 42 | // Removing the last element 43 | const actualResult = pop(); 44 | const expectedResult = 'El Hobbit'; 45 | 46 | assert.isTrue(size() === 4); // The size now should be 4 47 | assert.isTrue(expectedResult === actualResult); // The last element removed is 'El Hobbit' 48 | }); 49 | }); 50 | 51 | describe('#last', () => { 52 | it('should be a function', () => { 53 | assert.typeOf(last, 'function', 'last should be a function'); 54 | }); 55 | 56 | it('should return the last element', () => { 57 | // Getting the last element 58 | const actualResult = last(); 59 | const expectedResult = 'El Alquimista'; 60 | 61 | assert.isTrue(expectedResult === actualResult); // The last element is 'El Alquimista' 62 | }); 63 | }); 64 | 65 | describe('#hasElements', () => { 66 | it('should be a function', () => { 67 | assert.typeOf(hasElements, 'function', 'hasElements should be a function'); 68 | }); 69 | 70 | it('should return true if the stack has elements', () => { 71 | // The stack has elements? 72 | const actualResult = hasElements(); 73 | const expectedResult = true; 74 | 75 | assert.isTrue(expectedResult === actualResult); // The sack has elements! 76 | }); 77 | }); 78 | 79 | describe('#size', () => { 80 | it('should be a function', () => { 81 | assert.typeOf(size, 'function', 'size should be a function'); 82 | }); 83 | 84 | it('should return the current size of the stack', () => { 85 | // Getting the size of the actual stack 86 | const actualResult = size(); 87 | const expectedResult = 4; 88 | 89 | assert.isTrue(expectedResult === actualResult); // The sack has 4 elements! 90 | }); 91 | }); 92 | 93 | describe('#clear', () => { 94 | it('should be a function', () => { 95 | assert.typeOf(clear, 'function', 'clear should be a function'); 96 | }); 97 | 98 | it('should clear the stack', () => { 99 | // Clear stack 100 | clear(); 101 | 102 | const actualResult = size(); 103 | const expectedResult = 0; 104 | 105 | assert.isTrue(expectedResult === actualResult); // The sack has 0 elements! 106 | }); 107 | }); 108 | 109 | describe('#print', () => { 110 | it('should be a function', () => { 111 | assert.typeOf(print, 'function', 'print should be a function'); 112 | }); 113 | 114 | it('should print the current stack', () => { 115 | // Adding new elements 116 | push(10); 117 | push(20); 118 | push(30); 119 | 120 | const actualResult = print(); 121 | const expectedResult = '10,20,30'; 122 | 123 | assert.isTrue(expectedResult === actualResult); // The new stack is [10, 20, 30] 124 | }); 125 | }); 126 | }); 127 | -------------------------------------------------------------------------------- /test/globalTest.js: -------------------------------------------------------------------------------- 1 | // Adding babel support 2 | require('babel-register'); 3 | 4 | // Global methods 5 | global.assert = require('chai').assert; 6 | 7 | // Console.log colors 8 | global.cyan = '\x1b[36m%s\x1b[0m'; 9 | global.yellow = '\x1b[33m'; 10 | global.blue = '\x1b[34m'; 11 | global.green = '\x1b[32m'; 12 | global.red = '\x1b[31m'; 13 | global.magenta = '\x1b[35m'; 14 | --------------------------------------------------------------------------------