├── Ejercicios
├── 01-FindNeedle
│ ├── FindNeedle.js
│ └── README.md
├── 02-SumArray
│ ├── README.md
│ └── SumArray.js
├── 03-MaxValue
│ ├── MaxValue.js
│ └── README.md
├── 04-MultidimensionalSumArray
│ ├── MultidimensionalSumArray.js
│ └── README.md
├── 05-MinStack
│ ├── MinStack.js
│ └── README.md
├── 06-HasBalanceBrackets
│ ├── HasBalanceBrackets.js
│ └── README.md
├── 07-SolveGraph
│ ├── README.md
│ └── SolveGraph.js
├── 08-FindWordStartingWith
│ ├── FindWordStartingWith.js
│ └── README.md
├── 09-BinaryToDecimal
│ ├── BinaryToDecimal.js
│ └── README.md
├── 10-DecimalToBynary
│ ├── DecimalToBynary.js
│ └── README.md
├── 11-ClockMinuteAdder
│ ├── ClockMinuteAdder.js
│ └── README.md
├── 12-Intersection
│ ├── Intersection.js
│ └── README.md
├── 13-SubSetSum
│ ├── README.md
│ └── SubSetSum.js
├── 14-LongestIncreasingSubSequence
│ ├── LongestIncreasingSubSequence.js
│ └── README.md
├── 15-SpyOn
│ ├── README.md
│ └── SpyOn.js
├── 16-Curry
│ ├── Curry.js
│ └── README.md
└── Tests
│ ├── coverage
│ ├── clover.xml
│ ├── coverage-final.json
│ ├── lcov-report
│ │ ├── base.css
│ │ ├── block-navigation.js
│ │ ├── bracketValidator.js.html
│ │ ├── favicon.png
│ │ ├── index.html
│ │ ├── indexArray.js.html
│ │ ├── mayorGanancia.js.html
│ │ ├── minStack.js.html
│ │ ├── multidimensionalArray.js.html
│ │ ├── prettify.css
│ │ ├── prettify.js
│ │ ├── sort-arrow-sprite.png
│ │ └── sorter.js
│ └── lcov.info
│ ├── jest.config.js
│ ├── package-lock.json
│ ├── package.json
│ ├── problems
│ ├── binarioaDecimal.js
│ ├── bracketValidator.js
│ ├── decimalABinario.js
│ ├── indexArray.js
│ ├── maxValue
│ ├── mayorGanancia.js
│ ├── minStack.js
│ ├── multidimensionalArray.js
│ ├── nCapicua.js
│ └── stackOcurrencia.js
│ └── test
│ ├── 01-FindNeedle.spec.js
│ ├── 02-SumArray.spec.js
│ ├── 03-MaxValue.spec.js
│ ├── 04-multidimensionalArray.spec.js
│ ├── 05-minStack.spec.js
│ ├── 06-HasBalancedBrackets.spec.js
│ ├── 07-SolveGraph.spec.js
│ ├── 08-FindWordStartingWith.spec.js
│ ├── 09-binaryToDecimal.spec.js
│ ├── 10-DecimalToBinary.spec.js
│ ├── 11-ClockMinuteAdder.spec.js
│ ├── 12-InterSection.spec.js
│ ├── 13-SubSetSum.spec.js
│ ├── 14-SpyOn.spec.js
│ └── 15-Curry.spec.js
├── Plantillas.md
├── README.md
└── images
├── binary-decimal.png
├── emoticon_duda.png
├── emoticon_gafas.png
├── fantino.png
├── grafico_complejidad.png
├── graph 1.png
├── graph 2.png
├── graph.png
├── perro_programador.png
├── sumArray.png
└── sumArray_true_false.png
/Ejercicios/01-FindNeedle/FindNeedle.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | //needle: redux
5 | //
6 | //haystack: react-redux
7 | //
8 | //output: 5
9 | //
10 | //needle: puntual
11 | //
12 | //haystack: pinky
13 | //
14 | //output: -1
15 | //
16 |
17 | function FindNeedle(needle, haystack) {
18 | //Escribir la funcion
19 | }
20 |
--------------------------------------------------------------------------------
/Ejercicios/01-FindNeedle/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Find Needle
4 | ## Introducción
5 | Encontrar el indice de la primera aparición de un string (needle) dentro de otro (haystack).
6 |
7 | Es decir, el objetivo del ejercicio es determinar si el primer string, needle, esta dentro del segundo, haystack, y en dicho caso, devolver el indice en el que esto ocurre.
8 |
9 | #### Ejemplos
10 | ###### Lo encuentra
11 | **needle**: redux
12 | **haystack**: react-redux
13 | **output**: 6
14 |
15 | ###### No lo encuentra
16 | **needle**: puntual
17 | **haystack**: pinky
18 | **output**: -1
19 |
20 | En este caso, como el needle no se encuentra en el haystack el valor de salida es -1.
21 |
22 | #### IMPORTANTE
23 | Para la resolución de este ejercicio no se puede utilizar la función preexistente: indexOf( )
24 |
25 |
26 | ## Solución
27 | ### En palabras
28 | 1. Visitar cada caracter del haystack
29 | 2. Visitar cada caracter del needle, si el primer caracter coincide:
30 | 1. Comparar el segundo caracter del needle con el siguiente del haystack
31 | 2. Continuar hasta llegar al final del needle o hasta que una comparación no sea igual
32 | 1. Si llegamos al final del needle es que encontramos el indice
33 | 3. Si el primer caracter del needle no coincide, avanzo al próximo caracter
34 | 4. Llegamos al final del haystack y no encontramos ninguna coincidencia
35 |
36 | ### Primer Alternativa
37 | Ahora si, busquemos la forma de traducir lo que ya dijimos en palabras a código.
38 | Ademas, debemos evaluar la complejidad en tiempo y espacio.
39 | ```javascript
40 | const findNeedle = (haystack, needle) => {
41 | // iteramos sobre el haystack
42 | for (let haystackIndex = 0; haystackIndex < haystack.length; haystackIndex += 1) {
43 | // comenzamos a iterar sobre el needle
44 | for (let needleIndex = 0; needleIndex < needle.length; needleIndex += 1 ) {
45 | // comparamos la letra del needle en la que estamos con la letra del haystack
46 | // cuando no hay match cortamos de comparar el needle
47 | if (haystack[haystackIndex + needleIndex] !== needle[needleIndex]) break;
48 | // si terminamos de recorrer la needle devolvemos el haystackIndex
49 | if (needleIndex + 1 === needle.length) return haystackIndex;
50 | }
51 | }
52 | // una vez que termina el loop y no encontramos match devolvemos -1
53 | return -1;
54 | }
55 | ```
56 | Considerando **haystack.length = n** y **needle.length = m**
57 |
58 | Complejidad temporal | Complejidad espacial
59 | --|--
60 | O(n*m)|O(1)
61 |
62 | ### Segunda Alternativa
63 | Otra forma de resolver el ejercicio, es utilizando la función slice.
64 |
65 | ```javascript
66 | function findNeedle2(haystack, needle){
67 | // iterar sobre el haystack
68 | for (let i = 0; i < haystack.length; i += 1) {
69 | // si la substring matchea el neddle podemos devoler el valor de i
70 | if (haystack.slice(i, i + needle.length) === needle) {
71 | return i;
72 | }
73 | }
74 | return -1;
75 | }
76 | ```
77 | Considerando **haystack.length = n** y **needle.length = m**
78 |
79 | Complejidad temporal | Complejidad espacial
80 | --|--
81 | O(n*m)|O(1)
82 |
83 |
84 | ## Código
85 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/Jc2b/0).
86 |
--------------------------------------------------------------------------------
/Ejercicios/02-SumArray/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Sum Array
4 | ## Introducción
5 | En este caso se nos presentan dos elementos: una arreglo **ordenado** de números enteros y un número entero.
6 | El objetivo del ejercicio es encontrar si la combinación de dos números cualesquiera del arreglo, suman el número dado.
7 |
8 | #### Ejemplos
9 | ###### Existen dos valores
10 | **arreglo**: [2,4,5,9]
11 | **número**: 9
12 | **return**: true
13 |
14 | ###### No existen dos valores
15 | **arreglo**: [2,4,5,9]
16 | **número**: 12
17 | **return**: false
18 |
19 | ## Solución
20 | Como todo ejercicio, existen múltiples soluciones para un mismo problema.
21 | En este caso, analizáremos dos alternativas diferentes, luego determináremos cual es mejor.
22 |
23 | ### En palabras
24 | 1. Recorrer el arreglo con dos indices
25 | 2. Chequear si la suma de ambas posiciones da el valor pasado por parámetro
26 | 1. Si da, hemos terminado. Encontramos los valores buscados
27 | 2. Si no, seguimos avanzando
28 | 3. Si uno de los indices llego al final, hemos finalizado el recorrido y no existen dos valores en el arreglo que logren la suma esperada
29 |
30 | ### Primer alternativa: Solución naive
31 | ```javascript
32 | functionsumArray (arr, n) {
33 | // Itero sobre el arreglo
34 | for (let i = 0; i < arr.length - 1; i += 1) {
35 | // Itero sobre los números siguientes
36 | for (let j = i + 1; j < arr.length; j += 1) {
37 | // Veo si son iguales a la suma y devuelvo true
38 | if (arr[i] + arr[j] === n) return true;
39 | }
40 | }
41 | // Si termine de recorrer el arreglo devuelvo alse
42 | return false;
43 | }
44 | ```
45 |
46 | Complejidad Temporal | Complejidad Espacial
47 | --|--
48 | O(n^2)|O(1)
49 |
50 | ### Segunda alternativa: Mejor solución
51 | ```javascript
52 | function sumArray2 (arr, n) {
53 | // Creo un puntero para el principio y el final
54 | let start = 0;
55 | let end = arr.length - 1;
56 | // Mientras el puntero del principio sea menor al del final
57 | while (start < end) {
58 | // guardo el resultado de la suma
59 | const sum = arr[start] + arr[end];
60 | // Si son iguales devuelvo true
61 | if ( sum === n) return true;
62 | // Si es menor aumento el puntero de start
63 | else if (sum < n) start += 1;
64 | // Si es mayor decremento el puntero de end
65 | else end -= 1;
66 | }
67 | // Si salimos del for loop significa que no hay coincidencia
68 | return false;
69 | }
70 | ```
71 |
72 | Complejidad Temporal | Complejidad Espacial
73 | --|--
74 | O(n)|O(1)
75 |
76 | ## Código
77 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/Jh9N/0).
78 |
--------------------------------------------------------------------------------
/Ejercicios/02-SumArray/SumArray.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | // arreglo: [2,4,5,9]
5 | //
6 | // numero: 9
7 | //
8 | // return: true
9 | //
10 | // arreglo: [2,4,5,9]
11 | //
12 | // numero: 12
13 | //
14 | // return: false
15 | //
16 | function SumArray(array) {
17 | //Escribir la funcion
18 | }
19 |
--------------------------------------------------------------------------------
/Ejercicios/03-MaxValue/MaxValue.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | // acciones: [4, 3,2,5,11]
5 | //
6 | // mayor ganancia: 9
7 | //
8 |
9 | function MaxValue(array) {
10 | //Escribir la funcion
11 | }
12 |
--------------------------------------------------------------------------------
/Ejercicios/03-MaxValue/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Max Value
4 | ## Introducción
5 | Se nos presenta un arreglo de enteros, estos representan el valor de una acción con el pasar del tiempo. ¿El objetivo del ejercicio? Encontrar cuál es la máxima ganancia posible de comprar a un horario y vender a otro después.
6 |
7 |
8 | #### Ejemplo
9 | **acciones**: [4, 3, 2, 5, 11]
10 | **mayor ganancia**: 9
11 |
12 | Esta ganancia la obtenemos comprando la acción cuando su valor es de 2 y vendiéndola cuando a 11.
13 |
14 | ## Solución
15 |
16 | ### Primer alternativa: Solución Fuerza Bruta
17 | ```javascript
18 | const maxValue = (stocks) => {
19 | // guardamos la primer diferencia
20 | let max = stocks[1] - stocks[0];
21 | // iteramos sobre cada posibilidad de compra
22 | for (let i = 0; i < stocks.length - 1; i += 1) {
23 | // e iteramos sobre cada posibilidad de venta
24 | for (let j = i + 1; j < stocks.length; j += 1){
25 | // sacamos ganancia potencial
26 | const potential = stocks[j] - stocks[i];
27 | // y deducimos si nos quedamos con el potencial o con el viejo máximo
28 | max = potential > max ? potential : max;
29 | }
30 | }
31 | // devolvemos el máximo
32 | return max;
33 | };
34 | ```
35 |
36 | Complejidad Temporal | Complejidad Espacial
37 | --|--
38 | O(n^2)|O(1)
39 |
40 |
41 | ### Segunda alternativa: Solución Optima
42 | ```javascript
43 | const maxValue2 = (stocks) => {
44 | // guardamos la primer diferencia
45 | let max = stocks[1] - stocks[0];
46 | // guardamos el precio mínimo hasta el momento
47 | let minPrice = stocks[0];
48 | // iteramos sobre las stocks
49 | for (let i = 1; i < stocks.length; i += 1) {
50 | // sacamos la ganacia potencial
51 | const potencial = stocks[i] - minPrice;
52 | // Nos quedamos con el mayor valor
53 | max = Math.max(max, potencial);
54 | // nos quedamos con el precio mínimo
55 | minPrice = Math.min(minPrice, stocks[i]);
56 | }
57 | // devolvemos el máximo
58 | return max;
59 | };
60 | ```
61 |
62 | Complejidad Temporal | Complejidad Espacial
63 | --|--
64 | O(n)|O(1)
65 |
66 | ## Código
67 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/JjYI).
68 |
--------------------------------------------------------------------------------
/Ejercicios/04-MultidimensionalSumArray/MultidimensionalSumArray.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //mdArraySum([1,2,3,4]); //should return 10
4 | //
5 | //mdArraySum([ [2,4] , [1], [4,2,1] ]); //should return 14
6 | //
7 | //mdArraySum([ 2, [3,4], 5, [-3, [6 , [ 4,5 ] ] ] ]); //should return 26
8 | //
9 |
10 | function mdArraySum(array) {
11 | //Escribir la funcion
12 | }
13 |
--------------------------------------------------------------------------------
/Ejercicios/04-MultidimensionalSumArray/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Multi-Dimensional SumArray
3 | ## Introducción
4 | Ya trabajamos con arreglos de una unica dimension, ahora subiremos un escalón e iremos por arreglos de dos dimensiones, es decir, un arreglo de arreglos de enteros.
5 | En este caso, el objetivo es encontrar la suma de todos los elementos del arreglo.
6 |
7 | #### Ejemplos
8 | **mdArray**: [1,2,3,4]
9 | **output**: 10
10 |
11 | **mdArraySum**: [ [2,4] , [1], [4,2,1] ]
12 | **output**: 14
13 |
14 | **mdArraySum**: [ 2, [3,4], 5, [-3, [6 , [ 4,5 ] ] ] ]
15 | **output**: 26
16 |
17 | ## Solución
18 | ### En palabras
19 | Algunas consideraciones a tener en cuenta antes de implementar una solución.
20 |
21 | 1. La suma inicial es cero
22 | 2. Chequea cada elemento en el arreglo
23 | 1. Si no es un arreglo agrégalo a la suma
24 | 2. Si es un arreglo agrega la suma de todos sus elementos a la suma
25 | 3. Devuelve el total
26 |
27 | ### Primer Alternativa
28 | Podemos empezar a implementar la solución, pero antes tenemos que resolver una pregunta:
29 | ###### ¿Cómo podemos calcular la suma en los elementos de un sub-arreglo de un sub-arreglo? La respuesta es ***RECURSIÓN***
30 |
31 | ```javascript
32 | const mdArraySum = (arr) => {
33 | // Iniciamos la suma en 0
34 | let sum = 0;
35 | // Iteramos sobre el arreglo
36 | for (let i = 0; i < arr.length; i += 1) {
37 | // si es un arreglo le sumamos lo que devuelve llamar otra vez la función sobre ese arreglo
38 | if (Array.isArray(arr[i])) sum += mdArraySum(arr[i])
39 | // si no le sumamos al total
40 | else sum += arr[i]
41 | }
42 | // devolvemos el total
43 | return sum;
44 | }
45 | ```
46 | Considerando que **m es la cantidad de elementos en todos los arreglos** y **m el nivel máximo de profundidad** obtenemos los siguientes ordenes de complejidad.
47 |
48 | Complejidad Temporal | Complejidad Espacial
49 | --|--
50 | O(n)|O(m)
51 |
52 | ### Segunda alternativa
53 | Veamos una solución one-liner.
54 |
55 | ```javascript
56 | const mdArraySum2 = arr =>
57 | arr.reduce((total, elem) => total + (Array.isArray(elem) ? mdArraySum2(elem) : elem), 0)
58 | ```
59 |
60 | ## Código
61 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/Jl9b).
62 |
--------------------------------------------------------------------------------
/Ejercicios/05-MinStack/MinStack.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5 | //
6 |
7 | function MinStack() {
8 | // Escribir la funcion
9 | }
10 |
--------------------------------------------------------------------------------
/Ejercicios/05-MinStack/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Min Stack
4 | ## Introducción
5 | Para poder comprender el objetivo de esta actividad necesitamos saber **¿Qué es un stack?** Un stack, también conocido como pila es **LIFO** (Last-In First-Out), es decir, el último en entrar es el primero en salir.
6 |
7 | En este caso, el ejercicio es implementar un stack que tenga los siguientes métodos:
8 | 1. **push(value) :** añadir el elemento, value, al stack.
9 | 2. **pop ( ) :** sacar un elemento del stack.
10 | 3. **min ( ) :** obtener el elemento con el valor mínimo.
11 |
12 | #### Importante
13 | * **TODOS** los métodos mencionados anteriormente deben ser de O(1).
14 | * Para la resolución del ejercicio no se puede utilizar **ningún** *Array method*
15 |
16 | ## Solución
17 | ### En palabras
18 |
19 | 1. Implementar un stack normal
20 | 2. Luego, implementar un stack con un requisito mas > encontrar el mínimo
21 |
22 | ##### Importante
23 |
24 | **NO PUEDES** guardar el valor mínimo y cada vez que agregas un nuevo valor compararlo **¿POR QUÉ?**
25 | **( ! ) IDEA:** Tener una estructura separada para guardar el mínimo por cada nodo que se agrega, y cuando sacamos el nodo removemos ese mínimo
26 |
27 | ### Primer aproximación
28 | Una primer aproximación para la resolución de este ejercicio es realizar un stack común.
29 |
30 | ```javascript
31 | class Node{
32 | constructor(value) {
33 | this.value = value;
34 | this.next = null;
35 | }
36 | }
37 |
38 | class Stack{
39 | constructor(value) {
40 | this.top = null;
41 | }
42 |
43 | push(val) {
44 | if(!this.top) this.top = new Node(val);
45 | else {
46 | const newTop = new Node(val);
47 | newTop.next = this.top;
48 | this.top = newTop;
49 | }
50 | }
51 |
52 | pop() {
53 | const oldTop = this.top;
54 | this.top = oldTop && oldTop.next;
55 | return oldTop && oldTop.value;
56 | }
57 |
58 | peek() {
59 | return this.top && this.top.value
60 | }
61 | }
62 | ```
63 |
64 | ### Extendemos el stack
65 | Luego, mejoramos la resolución previamente presentada. Extendemos el stack para agregarle el mínimo
66 |
67 | ```javascript
68 | class MinStack extends Stack{
69 | constructor() {
70 | super();
71 | this.minimum = new Stack();
72 | }
73 |
74 | push(val) {
75 | if(!this.top) {
76 | this.top = new Node(val);
77 | this.minimum.push(val);
78 | }
79 | else {
80 | const newTop = new Node(val);
81 | newTop.next = this.top;
82 | this.top = newTop;
83 | if(this.minimum.peek() > val) this.minimum.push(val);
84 | else this.minimum.push(this.minimum.peek());
85 | }
86 | }
87 |
88 | pop() {
89 | const oldTop = this.top;
90 | this.top = oldTop && oldTop.next;
91 | this.minimum.pop();return oldTop && oldTop.value;
92 | }
93 |
94 | min() {
95 | return this.minimum.peek();
96 | }
97 | }
98 | ```
99 |
100 | ## Complejidad Espacial
101 | La complejidad espacial del ejercicio sigue siendo de O(n) con la diferencia que ahora almacenamos el doble de la información, O(2n)
102 |
103 | ## Código
104 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/JqWw).
105 |
--------------------------------------------------------------------------------
/Ejercicios/06-HasBalanceBrackets/HasBalanceBrackets.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // "{ [ ] ( ) }" debería devolver true
4 | //
5 | // "{ [ ( ] ) }" debería devolver false
6 | //
7 | // "{ [ }" debería devolver false
8 | //
9 | // "{ [ ( [ { ( )[ ]{ } } ] ) ] }" debería devolver true
10 | //
11 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12 | function HasBalanceBrackets() {
13 | // Escribir la funcion
14 | }
15 |
--------------------------------------------------------------------------------
/Ejercicios/06-HasBalanceBrackets/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Has Balance Brackets
4 | ## Introducción
5 | Crear un bracket validator. La idea es que chequee que los brackets estén balanceados correctamente.
6 |
7 | Los brackets válidos son los siguientes: **[ ] ( ) { }**
8 |
9 | ### Ejemplos
10 |
11 | **input:** "{ [ ] ( ) }"
12 | **output:** true
13 |
14 | **input:** "{ [ ( ] ) }"
15 | **output:** false
16 |
17 | **input:** "{ [ }"
18 | **output:** false
19 |
20 | **input:** "{ [ ( [ { ( )[ ]{ } } ] ) ] }"
21 | **output:** true
22 |
23 | ## Solución
24 | ### En Palabras
25 |
26 | 1. Tienes:
27 | * **"opening"** - **( { [** - y,
28 | * **"closing"** - **) } ]** - brackets.
29 | 2. Cada closing bracket tiene que corresponder con la opening bracket mas cercano que empareje.
30 | 3. Cada opening y closing bracket tienen que estar en pareja.
31 |
32 | Entonces tienen que ir trackeando los opening brackets y fijarse si cuando encontramos una closing bracket, matchea con la opening bracket mas cercana
33 |
34 | ##### ¿Qué estructura de datos podemos utilizar para esto?
35 |
36 | ### Solución posible
37 | ```javascript
38 | const hasBalancedBrackets = (string) => {
39 | // Tenemos un diccionario para chequear las opening brackets con sus closing brackets
40 | const validBrackets = {
41 | '{' : '}',
42 | '[' : ']',
43 | '(' : ')',
44 | };
45 | // creamos un arreglo donde vamos a ir guardando los openBrackets
46 | const openBrackets = [];
47 | // iteramos sobre el string
48 | for (let i = 0; i < string.length; i += 1) {
49 | // si existe la propiedad significa que es un opening bracket entonces lo guardamos
50 | if (validBrackets[string[i]]) {
51 | openBrackets.push(string[i]);
52 | } else if (validBrackets[openBrackets.pop()] !== string[i]) {
53 | // Si no nos fijamos que el closing bracket corresponda con el ultimo opening bracket
54 | return false;
55 | }
56 | }
57 | // una vez que terminamos de recorrer
58 | // chequeamos que no haya quedado nada en el arreglo
59 | return !openBrackets.length;
60 | };
61 | ```
62 |
63 | ## Conclusión
64 | * Las estructuras de datos pueden ser muy útiles aunque... no estemos explícitamente creando una.
65 | * Podemos usar arreglos y métodos del arreglo para crear un arreglo que se comporte como un stack/queue
66 |
67 | ## Código
68 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/JsIz).
69 |
--------------------------------------------------------------------------------
/Ejercicios/07-SolveGraph/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Solve Graph
4 | ## Introducción
5 | Un grafo/graph es un set de vertices conectados entre ellos por aristas.
6 |
7 | ### Undirected vs. Directed Graphs
8 |
9 |
10 |
11 |
12 | ### ¿Qué hay que hacer?
13 | Escribe una función que determine si existe un path entre dos vertices de un graph.
14 |
15 | El graph será representado como un objeto. Cada key representa un vértice. El valor, todos los vertices que pueden ser alcanzados.
16 |
17 | El graph, será un *'directed graph'*.
18 |
19 |
20 |
21 | Como observamos, en la imagen de la izquierda el nodo 'a' se conecta con el nodo 'b', el nodo 'b' con el nodo 'c' y 'd' y por último, el nodo 'c' con el nodo 'd'.
22 |
23 | ## Solución
24 | ### En palabras
25 | - La solución puede ser un algoritmo **Breadth-First** o **Depth-First**
26 | - Pero... los graphs pueden ser cíclicos
27 | - Si empezamos recorriendo el vértice A, eventualmente vamos a llegar al vértice R que apunta devuelta al A.
28 |
29 | ```javascript
30 | {
31 | a: ['c'],
32 | c: ['s', 'r'],
33 | r: ['a'],
34 | s: [ ]
35 | }
36 | ```
37 | - ¿El problema? Un algoritmo normal de BFS/DFS terminaría en un **loop infinito**.
38 | - Por lo tanto, tu algoritmo tiene que traquear todos los vertices que visitó
39 | - Si un vértice ha sido visitado sabemos que no tenemos que recorrer sus aristas por segunda vez
40 | - El **algoritmo se completa** cuando se ha encontrado el target o cuando todas las posibilidades fueron recorridas.
41 |
42 | ### Solución depth-first
43 |
44 | ```javascript
45 | const graph = {
46 | a: ['c'],
47 | b: ['c'],
48 | c: ['s', 'r'],
49 | d: ['a'],
50 | s: ['a', 'c'],
51 | r: ['d'],
52 | z: ['z']
53 | };
54 | function solveGraphDFS(graph, start, end, visited = {}) {
55 | // nos fijamos si ya visitamos este vértice
56 | if (visited[start]) return false;
57 | // lo agregamos a los visitados
58 | visited[start] = true;
59 | // iteramos sobre el arreglo de vértices
60 | for (let i = 0; i < graph[start].length; i += 1) {
61 | // Si encontramos el target devolvemos true
62 | if (end === graph[start][i]) return true;
63 | // si no llamamos recursivamente a la función para ver si sus aristas están conectadas
64 | else if (solveGraphDFS(graph, graph[start][i], end, visited)) return true
65 | }
66 | // si no devolvemos false
67 | return false;
68 | }
69 |
70 | solveGraphDFS(graph, 'a', 'r') // true
71 | solveGraphDFS(graph, 's', 'b') // false
72 | ```
73 |
74 | Complejidad Temporal | Complejidad Espacial
75 | --|--
76 | O(n)|O(n)
77 |
78 |
79 | ### Solución breadth-first approach
80 | ```javascript
81 | const graph = {
82 | a: ['c'],
83 | b: ['c'],
84 | c: ['s', 'r'],
85 | d: ['a'],
86 | s: ['a', 'c'],
87 | r: ['d'],
88 | z: ['z']
89 | };
90 | function solveGraphBFS(graph, start, end, visited = {}, queue = []) {
91 | // nos fijamos si ya visitamos este vértice
92 | if (visited[start]) return false;
93 | // lo agregamos a los visitados
94 | visited[start] = true;
95 | // iteramos sobre el arreglo de vértices
96 | for (let i = 0; i < graph[start].length; i += 1) {
97 | // agregamos todas sus conexiones al queue
98 | queue.push(graph[start][i]);
99 | }
100 | // comparamos si el siguiente del queue es nuestro target
101 | // sino llamamos recursivamente a la función con el start del siguiente del queue
102 | return queue[0] === end || solveGraphBFS(graph, queue.shift(), end, visited, queue);
103 | }
104 | solveGraphBFS(graph, 'a', 'r'); // true
105 | solveGraphBFS(graph, 's', 'b'); // false
106 | ```
107 | Complejidad Temporal | Complejidad Espacial
108 | --|--
109 | O(n)|O(n)
110 |
111 | ## Código
112 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/JuS9).
113 |
--------------------------------------------------------------------------------
/Ejercicios/07-SolveGraph/SolveGraph.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
5 |
6 | function SolveGraph(obj, vertice, vertice2) {
7 | // Escribir la funcion
8 | }
9 |
--------------------------------------------------------------------------------
/Ejercicios/08-FindWordStartingWith/FindWordStartingWith.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | // const book = {
3 | // id: 1,
4 | // text: 'Erase una vez un libro de palabras que era un poco aburrido pero tenia much
5 | // }
6 | // findWordsStartingWith(book, 'de') // [23, 112]
7 | // findWordsStartingWith(book, 'un') // [ 6, 14, 43, 99, 115 ]
8 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 |
10 | function FindWordStartingWith() {
11 | // Escribir la funcion
12 | }
13 |
--------------------------------------------------------------------------------
/Ejercicios/08-FindWordStartingWith/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Find Word Starting With
4 | ## Introducción
5 | Dado un "libro" y un string para buscar, devolver todos los indices donde la palabra empieza con ese string.
6 |
7 | El libro vendrá con dos cosas: un id y un texto. **La búsqueda tiene que ser case insensitive.**
8 |
9 | #### Ejemplo
10 | ```javascript
11 | const book = {
12 | id: 1,
13 | text: 'Erase una vez un libro de palabras que era un poco aburrido pero tenia muchas'
14 | }
15 | ```
16 |
17 | findWordsStartingWith **(book, 'de')**
18 | **output:** [23]
19 |
20 | findWordsStartingWith **(book, 'un')**
21 | **output:** [ 6, 14, 43]
22 |
23 |
24 | ## Solución
25 | ### Primer alternativa
26 | Una alternativa, **naive**, es iterar a través del texto.
27 | ```javascript
28 | const findWordsStartingWithNaive = (book, query) => {
29 | const separators = {
30 | ' ': true,
31 | '.': true,
32 | ',': true,
33 | }
34 | const text = book.text.toLowerCase();
35 | const finds = [];
36 | for (let i = 0; i < text.length; i += 1) {
37 | if (i !== 0 && !separators[text[i-1]]) continue;
38 | for (let j = 0; j < query.length; j += 1) {
39 | if (query[j] !== text[i + j]) {
40 | i += j;
41 | break;
42 | }
43 | if (j === query.length - 1){
44 | finds.push(i);
45 | i += j;
46 | }
47 | }
48 | }
49 | return finds;
50 | }
51 | ```
52 | **Complejidad temporal:** O(n)
53 |
54 | ### Segunda Alternativa
55 | Otra alternativa, es utilizar un **trie**. Pero ... ¿Que es un trie?
56 |
57 | #### Ejemplo
58 | ```javascript
59 | {
60 | [char]: {
61 | data: data,
62 | [nextChar]: {
63 | data: data,
64 | // ...
65 | }
66 | }
67 | }
68 | ```
69 | ###### ¿Podes encontrar el mensaje secreto?
70 |
71 | ```javascript
72 | const trie = {
73 | t: {
74 | indexes: [0, 5],
75 | o: {
76 | indexes:[0, 5],
77 | n: {
78 | indexes: [0, 5],
79 | i: {
80 | indexes: [0]
81 | },
82 | t: {
83 | indexes: [5],
84 | o:{
85 | indexes: [5]
86 | }
87 | }
88 | }
89 | }
90 | }
91 | }
92 | ```
93 | ###### Equivale a:
94 | ```javascript
95 | buildTrie('Toni tonto')
96 | ```
97 |
98 | #### ¿Por qué?
99 | Porque **repetir la ejecución va a ser mucho mas rápido con un árbol**.
100 |
101 |
102 | ### Paso 1: Haz el TRIE
103 | ```javascript
104 | const buildTrie = (text) => {
105 | const trie = {};
106 | const separators = {
107 | ' ': true,
108 | '.': true,
109 | ',': true,
110 | }
111 | for (let i = 0; i < text.length; i += 1) {
112 | let currentLetter = trie;
113 | const startingIndex = i;
114 | while(text[i] && !separators[text[i]]) {
115 | currentLetter[text[i]] = currentLetter[text[i]] || { indexes: [] }
116 | currentLetter = currentLetter[text[i]];
117 | currentLetter.indexes.push(startingIndex);
118 | i++;
119 | }
120 | }
121 | return trie;
122 | };
123 | ```
124 | ### Paso 2:
125 | Una vez que el TRIE es creado todo lo que necesitas hacer es **iterar a través del largo del string**, **recorrer los nodos hasta** que llegues al **final** y luego, **retornar el arreglo de indices en ese punto**.
126 |
127 | ```javascript
128 | const tries = {};
129 | const findOrCreateTrie = ({ id, text }) => {
130 | tries[id] = tries[id] || buildTrie(text);
131 | return tries[id];
132 | };
133 |
134 | const findWordsStartingWith = (book, query) => {
135 | const trie = findOrCreateTrie(book)
136 | let currentLetter = trie;
137 | query = query.toLowerCase();
138 | for (let i = 0; i < query.length && currentLetter; i++) {
139 | currentLetter = currentLetter[query[i]]
140 | }
141 | return currentLetter ? currentLetter.indexes: [];
142 | }
143 | ```
144 |
145 | ## Complejidad
146 | ### Buscar si hay que construir el TRIE
147 | Complejidad Temporal | Complejidad Espacial
148 | --|--
149 | O(n+m)|O(1)
150 |
151 | ### Buscar si el TRIE ya fue construido
152 | Complejidad Temporal | Complejidad Espacial
153 | --|--
154 | O(m)|O(1
155 |
156 | ## Código
157 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/JvdR/9).
158 |
--------------------------------------------------------------------------------
/Ejercicios/09-BinaryToDecimal/BinaryToDecimal.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | //
5 | //
6 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7 |
8 | function BinaryToDecimal() {
9 | // Escribir la funcion
10 | }
11 |
--------------------------------------------------------------------------------
/Ejercicios/09-BinaryToDecimal/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Binary to Decimal
4 | ## Introducción
5 | Escribe una función que pase un string en binario a un número decimal
6 |
7 | ## Solución
8 | ### En palabras
9 | 1. Iterar sobre cada número
10 | 2. Ir sumando: la potencia de 2 y, su posición, multiplicada por el número [1 ó 0].
11 |
12 | #### Ejemplo
13 |
14 |
15 |
16 |
17 | ### Primer alternativa
18 | ```javascript
19 | const binaryToDecimal = (binary) => {
20 | let sum = 0;
21 | for (let i = 0; i < binary.length; i += 1) {
22 | sum += Math.pow(2, binary.length - (i+1)) * binary[i];
23 | }
24 | return sum;
25 | };
26 | ```
27 |
28 | ### Segunda alternativa
29 | En este caso, se propone una **solución recursiva**.
30 | ```javascript
31 | const binaryToDecimalRec = (binary) => {
32 | const sum = Math.pow(2, binary.length - 1) * binary[0]
33 | if (binary.length !== 1) {
34 | return sum + binaryToDecimalRec(binary.slice(1));
35 | }
36 | return sum
37 | }
38 | ```
39 |
40 | ## Código
41 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KBgB/4).
42 |
--------------------------------------------------------------------------------
/Ejercicios/10-DecimalToBynary/DecimalToBynary.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | //
4 | //
5 | //
6 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7 |
8 | function DecimalToBynary() {
9 | // Escribir la funcion
10 | }
11 |
--------------------------------------------------------------------------------
/Ejercicios/10-DecimalToBynary/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Decimal to Binary
4 | ## Introducción
5 | En el caso anterior transformábamos números binarios en decimales. En este caso hay que **hacer una función que tome un numero decimal y lo devuelva en binario**
6 |
7 | ## Solución
8 | ### En palabras
9 | 1. Tomá el número y sacá su modulo en 2
10 | 2. Guardá el resultado en un string
11 | 3. Dividí el número por 2 y redondealo para abajo
12 | 4. Continúa el proceso hasta que el número sea igual a 0
13 | 5. Devuelve el string
14 |
15 | ### Primer alternativa
16 | ```javascript
17 | const decimalToBinary = (num) => {
18 | let binary = '';
19 | while(num) {
20 | binary = num % 2 + binary;
21 | num = Math.floor(num / 2);
22 | }
23 | return binary
24 | }
25 | ```
26 | ### Segunda alternativa
27 | En este caso, se propone una **solución recursiva**.
28 | ```javascript
29 | const decimalToBinaryRec = (num) => {
30 | if (num) {
31 | return decimalToBinaryRec(Math.floor(num / 2)) + num % 2
32 | }
33 | return '';
34 | }
35 | ```
36 | ## Código
37 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KDLz/1).
38 |
--------------------------------------------------------------------------------
/Ejercicios/11-ClockMinuteAdder/ClockMinuteAdder.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // clockMinuteAdder('09:00', 20); // '09:20'
4 | //
5 | // clockMinuteAdder('01:30', 30); // '02:00'
6 | //
7 | // clockMinuteAdder('12:05', 100); // '01:45'
8 | //
9 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
10 |
11 | function clockMinuteAdder() {
12 | // Escribir la funcion
13 | }
14 |
--------------------------------------------------------------------------------
/Ejercicios/11-ClockMinuteAdder/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Clock minute adder
4 | ## Introducción
5 | Dada una hora en string en **formato HH:MM**, y un número de minutos.
6 | Devolver la nueva hora pasados esos minutos.
7 |
8 | ##### IMPORTANTE
9 | El reloj es de 12 horas y tiene que devolverse en el formato HH:MM. Recuerda que no existen las 00hs.
10 |
11 | ##### Ejemplos:
12 | clockMinuteAdder (**'09:00', 20**);
13 | **ouput**: '09:20'
14 |
15 | clockMinuteAdder (**'01:30', 30**);
16 | **ouput**: '02:00'
17 |
18 | clockMinuteAdder (**'12:05', 100**);
19 | **ouput**: '01:45'
20 |
21 | ## Solución
22 | ```javascript
23 | const clockMinuteAdder = (time, minutesToAdd) => {
24 | // Separo las horas y los minutos
25 | const [hours, minutes] = time.split(':');
26 |
27 | // agrego el total de minutos y el total de horas
28 | const totalMinutes = (minutesToAdd + parseInt(minutes));
29 | const totalHours = Math.floor(totalMinutes/60) + parseInt(hours);
30 |
31 | // saco las nuevas horas y minutos
32 | const newHours = ((totalHours - 1) % 12) + 1 ; // para que no quede 0hrs
33 | const newMinutes = totalMinutes % 60;
34 |
35 | // le agrego formato de ceros adelante si es necesario
36 | const formatHours = newHours > 9 ? newHours : `0${newHours}`;
37 | const formatMinutes = newMinutes > 9 ? newMinutes : `0${newMinutes}`;
38 |
39 | //devuelvo la nueva hora
40 | return `${formatHours}:${formatMinutes}`;
41 | };
42 | ```
43 |
44 | ## Código
45 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KEvy/3).
46 |
--------------------------------------------------------------------------------
/Ejercicios/12-Intersection/Intersection.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Ej: [1,3,5,7,10], [2,3,6,8,10,20] => [3, 10]
4 | //
5 | //
6 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7 |
8 | function intersection() {
9 | // Escribir la funcion
10 | }
11 |
--------------------------------------------------------------------------------
/Ejercicios/12-Intersection/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Intersection
3 | ## Introducción
4 | Dado dos arreglos **ordenados** devuelve un
5 | arreglo con los números que se repiten.
6 |
7 | #### Ejemplos:
8 | **input**: [1,3,5,7,10], [2,3,6,8,10,20]
9 | **output**: [3, 10]
10 |
11 | ## Solución
12 | ### Primer alternativa: Fuerza Bruta
13 | ```javascript
14 | function intersection(arr1, arr2) {
15 | const result = [];
16 | arr1.forEach(num1 => {
17 | arr2.forEach(num2 => {
18 | if(num1 === num2) result.push(num1);
19 | });
20 | });
21 | return result;
22 | }
23 | ```
24 | Complejidad Temporal | Complejidad Espacial
25 | --|--
26 | O(n*m)|O(n)
27 |
28 | ### Segunda alternativa: Solución Optima
29 | ```javascript
30 | function intersection2(arr1, arr2) {
31 | let index1 = 0;
32 | let index2= 0;
33 | const result = [];
34 | while(index1 < arr1.length && index2 < arr2.length) {
35 | if (arr1[index1] === arr2[index2]) {
36 | result.push(arr1[index1]);
37 | index1 += 1;
38 | index2 += 1;
39 | }
40 | else if(arr1[index1] < arr2[index2]) index1 += 1;
41 | else index2 += 1
42 | }
43 | return result;
44 | }
45 | ```
46 | Complejidad Temporal | Complejidad Espacial
47 | --|--
48 | O(n+m)|O(n)
49 |
50 |
51 | ###### Pero... ¿Qué pasaría si el arreglo no estuviese ordenado?
52 |
53 | ### Para un arreglo desordenado
54 | ```javascript
55 | function intersection3(arr1, arr2) {
56 | const hashMap = arr1.reduce((memo, num) => {
57 | memo[num] = true;
58 | return memo;
59 | }, {});
60 | return arr2.filter(num => hashMap[num]);
61 | }
62 | ```
63 | Complejidad Temporal | Complejidad Espacial
64 | --|--
65 | O(n+m)|O(n)
66 |
67 | Como verán, la complejidad espacial sigue siendo O(n) **pero estamos creando n de espacio extra por el HashMap**.
68 |
69 | ## Código
70 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KKep/1).
71 |
--------------------------------------------------------------------------------
/Ejercicios/13-SubSetSum/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Subset Sum
3 | ## Introducción
4 | Dada una suma objetiva, 'target' y un arreglo de números positivos:
5 | * Devolvé **true** si cualquier combinación de números en el arreglo suma el target.
6 | * Devolvé **false** si los números no pueden ser usados para sumar el target
7 |
8 | ##### IMPORTANTE
9 | Cada número en el arreglo solo se puede usar una vez.
10 |
11 | #### Ejemplos:
12 | subsetSum( **[1,10,5,3], 9** );
13 | **output**: true <= 1 + 5 + 3
14 |
15 | subsetSum( **[1,10,5,3], 19** );
16 | **output**:true <= add all 4
17 |
18 | subsetSum( **[1,10,5,3], 17** );
19 | **output**:false
20 |
21 | subsetSum( **[1,10,5,3], 2** );
22 | **output**:false
23 |
24 | subsetSum( **[1,10,5,3], 10** );
25 | **output**:true <= 10 + 0 = 10
26 |
27 | ## Solución
28 | ### Primer alternativa: Iterativa
29 | #### En palabras
30 | Construir un arreglo de todas las sumas posibles:
31 | 1. Inicializa el arreglo de sumas con 0
32 | 2. Itera sobre el arreglo de números
33 | 3. Itera sobre el arreglo de sumas, chequeando si el elemento actual + la suma es igual al target
34 | 4. Si la nueva suma es menor que el target
35 | guardalo en el arreglo de sumas
36 |
37 | ##### Ejemplo:
38 | ```javascript
39 | subsetSum(17, [1, 10, 5, 3])
40 | => set de posibles sumas: [0]
41 | => agrega 1 a cada suma posible
42 | => set de posibles sumas: [0, 1]
43 | => agrega 10 a cada suma posible
44 | => set de sumas posibles: [0, 1, 10, 11]
45 | => agrega 5 a cada posible suma
46 | => set de sumas posibles: [0, 1, 10, 11, 5, 6, 15, 16]
47 | ```
48 |
49 | #### En código
50 | ```javascript
51 | const subsetSum = (nums, target) => {
52 | const sums = [0];
53 | return nums.some((num) => {
54 | const copySums = [...sums];
55 | return copySums.some(sum => {
56 | const newSum = sum + num;
57 | if (target === newSum) return true;
58 | if (newSum < target) sums.push(newSum);
59 | })
60 | })
61 | }
62 | ```
63 |
64 | ### Segunda alternativa: Optimización
65 | Con la alternativa anterior... Podemos estar agregando valores repetidos al arreglo que nos dan el mismo resultado
66 |
67 | ##### Ejemplo
68 | ```javascript
69 | => 1,2,3,4,5,6
70 | => 0,1,2,3,3,4,5,6,4,5,6,7
71 | ```
72 |
73 | ###### ¿Como podemos evitar agregar elementos repetidos sin agregar complejidad? Con UN SET.
74 |
75 | #### Solución Iterativa con Set
76 | ```javascript
77 | const subsetSumSet = (nums, target) => {
78 | const sums = new Set([0]);
79 | return nums.some((num) => {
80 | const copySums = [...sums];
81 | for (let sum of copySums) {
82 | const newSum = sum + num;
83 | if (target === newSum) return true;
84 | if (newSum < target) sums.add(newSum);
85 | }
86 | })
87 | }
88 | ```
89 |
90 | ### Tercer Alternativa: Solución Recursiva
91 | #### En palabras
92 | También podemos encarar este problema recursivamente.
93 |
94 | Por cada elemento del arreglo solo nos importa:
95 |
96 | 1. Usarlo para construir la suma nos va a ayudar a llegar al target
97 | 2. Saltearlo y añadir otros números va a hacernos llegar al target
98 | 3. Entonces... por cada elemento, hagamos una llamada recursiva que chequeé estas dos cosas
99 |
100 | #### En código
101 | ```javascript
102 | const subsetSumRec = (nums, target, index = 0) => {
103 | if (target === 0) return true;
104 | if (target < 0) return false;
105 | if (index > nums.length) return false;
106 | const whenExcluded = subsetSumRec(nums, target, index + 1)
107 | const whenIncluded = subsetSumRec(nums, target - nums[index], index + 1);
108 | return whenExcluded || whenIncluded
109 | }
110 | ```
111 |
112 | ###### Pero de nuevo estamos creando muchos caminos que se repiten...
113 |
114 |
115 | #### Optimización de la Solución Recursiva
116 | Con memoization podemos guardar los números que ya tuvimos un resultado y no tener que volver a procesarlos.
117 |
118 | ```javascript
119 | const subsetSumRecMemo = (nums, target, index = 0, memo = {}) => {
120 | if(memo.hasOwnProperty(target)) return memo[target];
121 | if (target === 0) return true;
122 | if (target < 0) return false;
123 | if (index > nums.length) return false;
124 | const whenIncluded = subsetSumRec(nums, target - nums[index], index + 1);
125 | const whenExcluded = subsetSumRec(nums, target, index + 1);
126 | memo[target] = whenExcluded;
127 | memo[target - nums[index]] = whenIncluded;
128 | return whenExcluded || whenIncluded ;
129 | }
130 | ```
131 | ## Complejidad
132 | Todas las soluciones son de complejidad:
133 |
134 | Complejidad Temporal | Complejidad Espacial
135 | --|--
136 | O(2^n)|O(2^n)
137 |
138 | Aunque algunas sean mas óptimas que otras, en el peor de los casos, hay que recorrer todo el arreglo, y no tener ninguna suma repetida.
139 |
140 | ## Código
141 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KM8S/4).
142 |
--------------------------------------------------------------------------------
/Ejercicios/13-SubSetSum/SubSetSum.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | // subsetSum(9, [1, 10, 5, 3]); // true, 1 + 5 + 3
3 | //
4 | // subsetSum(19, [1, 10, 5, 3]); // true, add all 4
5 | //
6 | // subsetSum(17, [1, 10, 5, 3]); // false
7 | //
8 | // subsetSum(2, [1, 10, 5, 3]); // false
9 | //
10 | // subsetSum(10, [1, 10, 5, 3]); // true, since 10 + 0 = 10
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
13 |
14 | function subsetSum(n, array) {
15 | // Escribir la funcion
16 | }
17 |
--------------------------------------------------------------------------------
/Ejercicios/14-LongestIncreasingSubSequence/LongestIncreasingSubSequence.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // longestIncreasingSubsequence([3, 4, 2, 1, 10, 6]);
4 | // debería devolver 3:
5 | // 3, 4, 6
6 | //
7 | // longestIncreasingSubsequence([10, 22, 9, 33, 20, 50, 41, 60, 80]);
8 | // debería devolver 6:
9 | // 10, 22, 33, 41, 60, 80 (or 10, 22, 33, 50, 60, 80)
10 | //
11 | // longestIncreasingSubsequence([10, 22, 9, 33, 20, 50, 41, 60, 80, 21, 23, 24, 25, 26, 27, 28]);
12 | // debería devolver 9:
13 | // 10, 20, 21, 23, 24, 25, 26, 27, 28
14 | //
15 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 |
17 | function longestIncreasingSubsequence() {
18 | // Escribir la funcion
19 | }
20 |
--------------------------------------------------------------------------------
/Ejercicios/14-LongestIncreasingSubSequence/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Longest Increasing Subsequence
3 | ## Introducción
4 | Dado un arreglo de números, encontrá el length de la secuencia creciente mas larga posible. Esta secuencia puede saltear números en el arreglo.
5 |
6 | #### Ejemplos
7 | **input:** [3,10,4,5]
8 | La **secuencia es [3,4,5]**
9 | **output:** 3.
10 |
11 |
12 | longestIncreasingSubsequence(**[3, 4, 2, 1, 10, 6]**);
13 | Donde la **secuencia** es: 3, 4, 6
14 | **output**: 3
15 |
16 |
17 | longestIncreasingSubsequence(**[10, 22, 9, 33, 20, 50, 41, 60, 80]**);
18 | Donde la **secuencia** es: 10, 22, 33, 41, 60, 80 (or 10, 22, 33, 50, 60, 80)
19 | **output**: 6
20 |
21 | longestIncreasingSubsequence(**[10, 22, 9, 33, 20, 50, 41, 60, 80, 21, 23, 24, 25, 26, 27, 28]**);
22 | Donde, la **secuencia** es: 10, 20, 21, 23, 24, 25, 26, 27, 28
23 | **output**: 9
24 |
25 | ## Solución
26 | ### Primer Alterantiva: Fuerza Bruta
27 | Recorrer todas las posibilidades de subsecuencias y quedarse con la mas grande.
28 |
29 | ```javascript
30 | function IterativeLIS (nums) {
31 | const sequences = [[-Infinity]];
32 | nums.forEach(num => {
33 | const copySeq = [...sequences];
34 | copySeq.forEach(sequence => {
35 | if(sequence.slice(-1)[0] < num) sequences.push([...sequence, num]);
36 | });
37 | });
38 | return sequences.reduce((memo, seq) => {
39 | if (memo > seq.length) return memo;
40 | return seq.length;
41 | }, 1) -1;
42 | }
43 | ```
44 |
45 | Recorrer todas las posibilidades de subsecuencias incluyendo o no incluyendo ese número
46 | ```javascript
47 | function longestIncreasingSubsequence (nums, index = 0, base = -Infinity) {
48 | // si ya recorrimos todo el arreglo devolver cero ya que termino la secuencia
49 | if (index === nums.length) return 0;
50 | // sacar la longitud de la secuencia que llego cuando le numero es excluido
51 | const whenExcluded = longestIncreasingSubsequence(nums, index + 1, base);
52 | // fijarse si el numero es menor que el numero que llega en la base
53 | // si es menor directamente devolver el excluido
54 | if (nums[index] <= base) return whenExcluded;
55 | // Tomar el valor cuando es incluido en la secuencia sumandole uno por si mismo
56 | const whenIncluded = 1 + longestIncreasingSubsequence(nums, index + 1, nums[index]);
57 | // devolver el mayor entre el incluido y el no incluido
58 | return Math.max(whenIncluded, whenExcluded);
59 | }
60 | ```
61 |
62 | #### Complejidad Temporal
63 | La complejidad de tiempo de esta solución es **O(2^n)**.
64 |
65 | Pero, siempre que tomamos el **whenIncluded** de un elemento ese valor es siempre el mismo... ¿Por qué no lo guardamos? **Memoization FTW**
66 |
67 | ### Segunda Alternativa: Solución con Memoization
68 | ```javascript
69 | function memoLis (nums, index = 0, base = -Infinity, memo = {}) {
70 | if (index === nums.length) return 0;
71 | const whenExcluded = memoLis(nums, index + 1, base, memo);
72 | if (nums[index] <= base) return whenExcluded;
73 | let whenIncluded;
74 | if(memo.hasOwnProperty(index)) whenIncluded = memo[index]
75 | else {
76 | whenIncluded = 1 + memoLis(nums, index + 1, nums[index], memo);
77 | memo[index] = whenIncluded;
78 | }
79 | return Math.max(whenIncluded, whenExcluded);
80 | }
81 | ```
82 | Fijense que **solo guardamos el whenIncluded**, ya que en el excluido la base puede ser distinta y dar distintos resultados.
83 |
84 | #### Complejidad Temporal
85 | En este caso, la complejidad temporal es de **O(n^2)**. ¿Por qué? Porque por cada elemento recorremos solo una vez en todos los elementos.
86 |
87 | ## Código
88 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KOFI/4).
89 |
--------------------------------------------------------------------------------
/Ejercicios/15-SpyOn/README.md:
--------------------------------------------------------------------------------
1 |
2 | # spyOn
3 | ## Introducción
4 | Implementa tu propia versión de la función **spyOn** que hace lo siguiente:
5 | - Toma una función como parámetro
6 | - Devuelve una función spy que toma cualquier numero de argumentos
7 | - spy llama a la función y devuelve lo que ella devuelve
8 | - spy tiene los siguientes métodos:
9 | - **.getCallCount()**: Devuelve la cantidad de veces que el spy fue llamado
10 | - **.wasCalledWith(val)**: devuelve true si la función fue alguna vez llamada con ese valor, else false
11 | - **.returned(val)**: devuelve true si alguna vez devolvió ese valor.
12 |
13 | #### Ejemplos:
14 | ```javascript
15 | function adder(n1, n2) { return n1 + n2; }
16 |
17 | const adderSpy = spyOn( adder );
18 |
19 | adderSpy.getCallCount(); // 0
20 |
21 | adderSpy(2, 4); // returns 6
22 | adderSpy.getCallCount(); // 1
23 |
24 | adderSpy(3, 5); // returns 8
25 | adderSpy.getCallCount(); // 2
26 | adderSpy.wasCalledWith(2); // true
27 | adderSpy.wasCalledWith(0); // false
28 | adderSpy.returned(6); // true
29 | adderSpy.returned(9); // false
30 | ```
31 |
32 | ## Solución
33 | ```javascript
34 | const spyOn = (fn) => {
35 | let callCount = 0;
36 | const calledWith = new Set();
37 | const returns = new Set();
38 | const spy = (...args) => {
39 | callCount += 1;
40 | args.forEach(arg => calledWith.add(arg));
41 | const result = fn(...args);
42 | returns.add(result);
43 | return result;
44 | }
45 | spy.getCallCount = () => callCount;
46 | spy.wasCalledWith = (val) => calledWith.has(val);
47 | spy.returned = (val) => returns.has(val);
48 | return spy;
49 | }
50 | ```
51 |
52 | ## Código
53 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KUom).
54 |
--------------------------------------------------------------------------------
/Ejercicios/15-SpyOn/SpyOn.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // function adder(n1, n2) {
4 | // return n1 + n2;
5 | // }
6 | // const adderSpy = spyOn(adder);
7 | // adderSpy.getCallCount(); // 0
8 | // adderSpy(2, 4); // returns 6
9 | // adderSpy.getCallCount(); // 1
10 | // adderSpy(3, 5); // returns 8
11 | // adderSpy.getCallCount(); // 2
12 | // adderSpy.wasCalledWith(2); // true
13 | // adderSpy.wasCalledWith(0); // false
14 | // adderSpy.returned(6); // true
15 | // adderSpy.returned(9); // false
16 | //
17 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18 |
19 | function spyOn() {
20 | // Escribir la funcion
21 | }
22 |
--------------------------------------------------------------------------------
/Ejercicios/16-Curry/Curry.js:
--------------------------------------------------------------------------------
1 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 | //
3 | // function calcAllFour(var1, var2, var3, var4) {
4 | // return var1 + var2 - var3 * var4;
5 | // }
6 | // const curriedDoSomething = curry(calcAllFour); //argumentos -> []
7 | // const firstReturn = curriedDoSomething(1); // argumentos -> [1]
8 | // const secondReturn = firstReturn(2); // argumentos -> [1, 2]
9 | // const thirdReturn = secondReturn(3); // argumentos -> [1, 2, 3]
10 | // const fourthReturn = thirdReturn(4); // -9 -> (1 + 2 - 3 * 4)
11 | //
12 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
13 |
14 | function Curry() {
15 | // Escribir la funcion
16 | }
17 |
--------------------------------------------------------------------------------
/Ejercicios/16-Curry/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Curry
3 | ## Introducción
4 | ¿Que es **currying**? Consiste en **transformar una función** que utiliza múltiples argumentos en una secuencia de funciones que utilizan un único argumento.
5 |
6 | #### Ejemplos
7 | ```javascript
8 | function calcAllFour(var1, var2, var3, var4) {
9 | return var1 + var2 - var3 * var4;
10 | }
11 | const curriedDoSomething = curry(calcAllFour); //argumentos -> []
12 | const firstReturn = curriedDoSomething(1); // argumentos -> [1]
13 | const secondReturn = firstReturn(2); // argumentos -> [1, 2]
14 | const thirdReturn = secondReturn(3); // argumentos -> [1, 2, 3]
15 | const fourthReturn = thirdReturn(4); // -9 -> (1 + 2 - 3 * 4)
16 | ```
17 |
18 | ## Solución
19 | ### En palabras
20 | Ahora haz el Curry:
21 | - Implementa la función "curry"
22 | - Mantén en mente
23 | - Tenés que saber cuantos argumentos la función que estas 'curring' toma.
24 | - La función anterior tenía 4 parámetros
25 | - La función que devuelvas del "curring" tiene acumuladas los argumentos anteriores.
26 | - La función debe determinar si los argumentos acumulados son iguales al numero de parámetros que la función original requiere, y devolver lo que la función original devolvería con los argumentos acumulados.
27 |
28 | ### Primer Alternativa: Solución ES5
29 | ```javascript
30 | function curry(fn) {
31 | return function curriedFn() {
32 | var args = [].slice.call(arguments);
33 | if (args.length >= fn.length) {
34 | return fn.apply(null, args);
35 | } else {
36 | return function resolver() {
37 | return curriedFn.apply(null, args.concat([].slice.call(arguments)));
38 | };
39 | }
40 | };
41 | };
42 | ```
43 |
44 | ### Segunda Alternativa: Solución ES6
45 | ```javascript
46 | const curry = (fn) => {
47 | return function curriedFn(...args) {
48 | if (args.length >= fn.length) return fn(...args);
49 | else return (...nextArgs) => curriedFn(...args, ...nextArgs);
50 | };
51 | };
52 | ```
53 |
54 | ## Código
55 | Pueden encontrar las soluciones recién mencionadas en el siguiente [link](https://repl.it/KWvq/1).
56 |
--------------------------------------------------------------------------------
/Ejercicios/Tests/coverage/clover.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
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 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Ejercicios/Tests/coverage/coverage-final.json:
--------------------------------------------------------------------------------
1 | {"/home/alemendoza/SoyHenry/reactoTesting/problems/bracketValidator.js": {"path":"/home/alemendoza/SoyHenry/reactoTesting/problems/bracketValidator.js","statementMap":{"0":{"start":{"line":9,"column":0},"end":{"line":27,"column":1}},"1":{"start":{"line":11,"column":20},"end":{"line":15,"column":5}},"2":{"start":{"line":16,"column":24},"end":{"line":16,"column":26}},"3":{"start":{"line":17,"column":4},"end":{"line":25,"column":5}},"4":{"start":{"line":17,"column":17},"end":{"line":17,"column":18}},"5":{"start":{"line":18,"column":8},"end":{"line":24,"column":22}},"6":{"start":{"line":19,"column":12},"end":{"line":19,"column":39}},"7":{"start":{"line":21,"column":13},"end":{"line":24,"column":22}},"8":{"start":{"line":22,"column":12},"end":{"line":22,"column":25}},"9":{"start":{"line":24,"column":13},"end":{"line":24,"column":22}},"10":{"start":{"line":26,"column":4},"end":{"line":26,"column":31}}},"fnMap":{"0":{"name":"bracketValidator","decl":{"start":{"line":9,"column":26},"end":{"line":9,"column":42}},"loc":{"start":{"line":9,"column":51},"end":{"line":27,"column":1}},"line":9}},"branchMap":{"0":{"loc":{"start":{"line":18,"column":8},"end":{"line":24,"column":22}},"type":"if","locations":[{"start":{"line":18,"column":8},"end":{"line":24,"column":22}},{"start":{"line":18,"column":8},"end":{"line":24,"column":22}}],"line":18},"1":{"loc":{"start":{"line":21,"column":13},"end":{"line":24,"column":22}},"type":"if","locations":[{"start":{"line":21,"column":13},"end":{"line":24,"column":22}},{"start":{"line":21,"column":13},"end":{"line":24,"column":22}}],"line":21}},"s":{"0":1,"1":4,"2":4,"3":4,"4":4,"5":27,"6":16,"7":11,"8":2,"9":9,"10":2},"f":{"0":4},"b":{"0":[16,11],"1":[2,9]},"_coverageSchema":"43e27e138ebf9cfc5966b082cf9a028302ed4184","hash":"121007457739d27a8d05c936043786fa0f00710c"}
2 | ,"/home/alemendoza/SoyHenry/reactoTesting/problems/indexArray.js": {"path":"/home/alemendoza/SoyHenry/reactoTesting/problems/indexArray.js","statementMap":{"0":{"start":{"line":15,"column":0},"end":{"line":29,"column":3}},"1":{"start":{"line":17,"column":4},"end":{"line":26,"column":5}},"2":{"start":{"line":17,"column":29},"end":{"line":17,"column":30}},"3":{"start":{"line":19,"column":6},"end":{"line":25,"column":7}},"4":{"start":{"line":19,"column":29},"end":{"line":19,"column":30}},"5":{"start":{"line":22,"column":8},"end":{"line":22,"column":81}},"6":{"start":{"line":22,"column":75},"end":{"line":22,"column":81}},"7":{"start":{"line":24,"column":8},"end":{"line":24,"column":68}},"8":{"start":{"line":24,"column":47},"end":{"line":24,"column":68}},"9":{"start":{"line":28,"column":4},"end":{"line":28,"column":14}}},"fnMap":{"0":{"name":"findNeedle","decl":{"start":{"line":15,"column":27},"end":{"line":15,"column":37}},"loc":{"start":{"line":15,"column":56},"end":{"line":29,"column":3}},"line":15}},"branchMap":{"0":{"loc":{"start":{"line":22,"column":8},"end":{"line":22,"column":81}},"type":"if","locations":[{"start":{"line":22,"column":8},"end":{"line":22,"column":81}},{"start":{"line":22,"column":8},"end":{"line":22,"column":81}}],"line":22},"1":{"loc":{"start":{"line":24,"column":8},"end":{"line":24,"column":68}},"type":"if","locations":[{"start":{"line":24,"column":8},"end":{"line":24,"column":68}},{"start":{"line":24,"column":8},"end":{"line":24,"column":68}}],"line":24}},"s":{"0":1,"1":2,"2":2,"3":18,"4":18,"5":24,"6":17,"7":7,"8":1,"9":1},"f":{"0":2},"b":{"0":[17,7],"1":[1,6]},"_coverageSchema":"43e27e138ebf9cfc5966b082cf9a028302ed4184","hash":"b200153bafd513e4dff3b4b979ea5610e161cc20"}
3 | ,"/home/alemendoza/SoyHenry/reactoTesting/problems/mayorGanancia.js": {"path":"/home/alemendoza/SoyHenry/reactoTesting/problems/mayorGanancia.js","statementMap":{"0":{"start":{"line":5,"column":0},"end":{"line":18,"column":1}},"1":{"start":{"line":6,"column":22},"end":{"line":6,"column":57}},"2":{"start":{"line":7,"column":4},"end":{"line":16,"column":5}},"3":{"start":{"line":7,"column":17},"end":{"line":7,"column":18}},"4":{"start":{"line":8,"column":8},"end":{"line":14,"column":9}},"5":{"start":{"line":8,"column":21},"end":{"line":8,"column":26}},"6":{"start":{"line":9,"column":36},"end":{"line":9,"column":71}},"7":{"start":{"line":11,"column":12},"end":{"line":13,"column":13}},"8":{"start":{"line":12,"column":16},"end":{"line":12,"column":48}},"9":{"start":{"line":17,"column":4},"end":{"line":17,"column":23}}},"fnMap":{"0":{"name":"mayorGanancia","decl":{"start":{"line":5,"column":26},"end":{"line":5,"column":39}},"loc":{"start":{"line":5,"column":55},"end":{"line":18,"column":1}},"line":5}},"branchMap":{"0":{"loc":{"start":{"line":11,"column":12},"end":{"line":13,"column":13}},"type":"if","locations":[{"start":{"line":11,"column":12},"end":{"line":13,"column":13}},{"start":{"line":11,"column":12},"end":{"line":13,"column":13}}],"line":11}},"s":{"0":1,"1":2,"2":2,"3":2,"4":8,"5":8,"6":20,"7":20,"8":8,"9":2},"f":{"0":2},"b":{"0":[8,12]},"_coverageSchema":"43e27e138ebf9cfc5966b082cf9a028302ed4184","hash":"6f3c18e08027397aacd8a41b21332a52e4564bfe"}
4 | ,"/home/alemendoza/SoyHenry/reactoTesting/problems/minStack.js": {"path":"/home/alemendoza/SoyHenry/reactoTesting/problems/minStack.js","statementMap":{"0":{"start":{"line":16,"column":8},"end":{"line":16,"column":27}},"1":{"start":{"line":17,"column":8},"end":{"line":17,"column":25}},"2":{"start":{"line":23,"column":8},"end":{"line":23,"column":28}},"3":{"start":{"line":27,"column":8},"end":{"line":35,"column":9}},"4":{"start":{"line":28,"column":12},"end":{"line":28,"column":47}},"5":{"start":{"line":32,"column":30},"end":{"line":32,"column":48}},"6":{"start":{"line":33,"column":12},"end":{"line":33,"column":42}},"7":{"start":{"line":34,"column":12},"end":{"line":34,"column":37}},"8":{"start":{"line":39,"column":29},"end":{"line":39,"column":41}},"9":{"start":{"line":40,"column":8},"end":{"line":40,"column":57}},"10":{"start":{"line":41,"column":8},"end":{"line":41,"column":50}},"11":{"start":{"line":45,"column":8},"end":{"line":45,"column":50}}},"fnMap":{"0":{"name":"(anonymous_0)","decl":{"start":{"line":15,"column":4},"end":{"line":15,"column":5}},"loc":{"start":{"line":15,"column":23},"end":{"line":18,"column":5}},"line":15},"1":{"name":"(anonymous_1)","decl":{"start":{"line":22,"column":4},"end":{"line":22,"column":5}},"loc":{"start":{"line":22,"column":17},"end":{"line":24,"column":5}},"line":22},"2":{"name":"(anonymous_2)","decl":{"start":{"line":26,"column":4},"end":{"line":26,"column":5}},"loc":{"start":{"line":26,"column":19},"end":{"line":36,"column":5}},"line":26},"3":{"name":"(anonymous_3)","decl":{"start":{"line":38,"column":4},"end":{"line":38,"column":5}},"loc":{"start":{"line":38,"column":10},"end":{"line":42,"column":5}},"line":38},"4":{"name":"(anonymous_4)","decl":{"start":{"line":44,"column":4},"end":{"line":44,"column":5}},"loc":{"start":{"line":44,"column":9},"end":{"line":46,"column":5}},"line":44}},"branchMap":{"0":{"loc":{"start":{"line":27,"column":8},"end":{"line":35,"column":9}},"type":"if","locations":[{"start":{"line":27,"column":8},"end":{"line":35,"column":9}},{"start":{"line":27,"column":8},"end":{"line":35,"column":9}}],"line":27},"1":{"loc":{"start":{"line":40,"column":23},"end":{"line":40,"column":56}},"type":"binary-expr","locations":[{"start":{"line":40,"column":23},"end":{"line":40,"column":35}},{"start":{"line":40,"column":39},"end":{"line":40,"column":56}}],"line":40},"2":{"loc":{"start":{"line":41,"column":15},"end":{"line":41,"column":49}},"type":"binary-expr","locations":[{"start":{"line":41,"column":15},"end":{"line":41,"column":27}},{"start":{"line":41,"column":31},"end":{"line":41,"column":49}}],"line":41},"3":{"loc":{"start":{"line":45,"column":15},"end":{"line":45,"column":49}},"type":"binary-expr","locations":[{"start":{"line":45,"column":15},"end":{"line":45,"column":27}},{"start":{"line":45,"column":31},"end":{"line":45,"column":49}}],"line":45}},"s":{"0":0,"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0},"f":{"0":0,"1":0,"2":0,"3":0,"4":0},"b":{"0":[0,0],"1":[0,0],"2":[0,0],"3":[0,0]},"_coverageSchema":"43e27e138ebf9cfc5966b082cf9a028302ed4184","hash":"6cd186d45be88a28e7e0383db0468a8d2c907404"}
5 | ,"/home/alemendoza/SoyHenry/reactoTesting/problems/multidimensionalArray.js": {"path":"/home/alemendoza/SoyHenry/reactoTesting/problems/multidimensionalArray.js","statementMap":{"0":{"start":{"line":4,"column":0},"end":{"line":14,"column":3}},"1":{"start":{"line":5,"column":14},"end":{"line":5,"column":15}},"2":{"start":{"line":6,"column":4},"end":{"line":12,"column":5}},"3":{"start":{"line":6,"column":17},"end":{"line":6,"column":18}},"4":{"start":{"line":7,"column":6},"end":{"line":11,"column":7}},"5":{"start":{"line":8,"column":8},"end":{"line":8,"column":40}},"6":{"start":{"line":10,"column":8},"end":{"line":10,"column":29}},"7":{"start":{"line":13,"column":4},"end":{"line":13,"column":15}}},"fnMap":{"0":{"name":"mDSumArray","decl":{"start":{"line":4,"column":26},"end":{"line":4,"column":36}},"loc":{"start":{"line":4,"column":44},"end":{"line":14,"column":3}},"line":4}},"branchMap":{"0":{"loc":{"start":{"line":7,"column":6},"end":{"line":11,"column":7}},"type":"if","locations":[{"start":{"line":7,"column":6},"end":{"line":11,"column":7}},{"start":{"line":7,"column":6},"end":{"line":11,"column":7}}],"line":7}},"s":{"0":1,"1":10,"2":10,"3":10,"4":25,"5":7,"6":18,"7":10},"f":{"0":10},"b":{"0":[7,18]},"_coverageSchema":"43e27e138ebf9cfc5966b082cf9a028302ed4184","hash":"2c2fbbb4967fbfb8eee946e6461f76dd0e68837a"}
6 | }
7 |
--------------------------------------------------------------------------------
/Ejercicios/Tests/coverage/lcov-report/base.css:
--------------------------------------------------------------------------------
1 | body, html {
2 | margin:0; padding: 0;
3 | height: 100%;
4 | }
5 | body {
6 | font-family: Helvetica Neue, Helvetica, Arial;
7 | font-size: 14px;
8 | color:#333;
9 | }
10 | .small { font-size: 12px; }
11 | *, *:after, *:before {
12 | -webkit-box-sizing:border-box;
13 | -moz-box-sizing:border-box;
14 | box-sizing:border-box;
15 | }
16 | h1 { font-size: 20px; margin: 0;}
17 | h2 { font-size: 14px; }
18 | pre {
19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace;
20 | margin: 0;
21 | padding: 0;
22 | -moz-tab-size: 2;
23 | -o-tab-size: 2;
24 | tab-size: 2;
25 | }
26 | a { color:#0074D9; text-decoration:none; }
27 | a:hover { text-decoration:underline; }
28 | .strong { font-weight: bold; }
29 | .space-top1 { padding: 10px 0 0 0; }
30 | .pad2y { padding: 20px 0; }
31 | .pad1y { padding: 10px 0; }
32 | .pad2x { padding: 0 20px; }
33 | .pad2 { padding: 20px; }
34 | .pad1 { padding: 10px; }
35 | .space-left2 { padding-left:55px; }
36 | .space-right2 { padding-right:20px; }
37 | .center { text-align:center; }
38 | .clearfix { display:block; }
39 | .clearfix:after {
40 | content:'';
41 | display:block;
42 | height:0;
43 | clear:both;
44 | visibility:hidden;
45 | }
46 | .fl { float: left; }
47 | @media only screen and (max-width:640px) {
48 | .col3 { width:100%; max-width:100%; }
49 | .hide-mobile { display:none!important; }
50 | }
51 |
52 | .quiet {
53 | color: #7f7f7f;
54 | color: rgba(0,0,0,0.5);
55 | }
56 | .quiet a { opacity: 0.7; }
57 |
58 | .fraction {
59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
60 | font-size: 10px;
61 | color: #555;
62 | background: #E8E8E8;
63 | padding: 4px 5px;
64 | border-radius: 3px;
65 | vertical-align: middle;
66 | }
67 |
68 | div.path a:link, div.path a:visited { color: #333; }
69 | table.coverage {
70 | border-collapse: collapse;
71 | margin: 10px 0 0 0;
72 | padding: 0;
73 | }
74 |
75 | table.coverage td {
76 | margin: 0;
77 | padding: 0;
78 | vertical-align: top;
79 | }
80 | table.coverage td.line-count {
81 | text-align: right;
82 | padding: 0 5px 0 20px;
83 | }
84 | table.coverage td.line-coverage {
85 | text-align: right;
86 | padding-right: 10px;
87 | min-width:20px;
88 | }
89 |
90 | table.coverage td span.cline-any {
91 | display: inline-block;
92 | padding: 0 5px;
93 | width: 100%;
94 | }
95 | .missing-if-branch {
96 | display: inline-block;
97 | margin-right: 5px;
98 | border-radius: 3px;
99 | position: relative;
100 | padding: 0 4px;
101 | background: #333;
102 | color: yellow;
103 | }
104 |
105 | .skip-if-branch {
106 | display: none;
107 | margin-right: 10px;
108 | position: relative;
109 | padding: 0 4px;
110 | background: #ccc;
111 | color: white;
112 | }
113 | .missing-if-branch .typ, .skip-if-branch .typ {
114 | color: inherit !important;
115 | }
116 | .coverage-summary {
117 | border-collapse: collapse;
118 | width: 100%;
119 | }
120 | .coverage-summary tr { border-bottom: 1px solid #bbb; }
121 | .keyline-all { border: 1px solid #ddd; }
122 | .coverage-summary td, .coverage-summary th { padding: 10px; }
123 | .coverage-summary tbody { border: 1px solid #bbb; }
124 | .coverage-summary td { border-right: 1px solid #bbb; }
125 | .coverage-summary td:last-child { border-right: none; }
126 | .coverage-summary th {
127 | text-align: left;
128 | font-weight: normal;
129 | white-space: nowrap;
130 | }
131 | .coverage-summary th.file { border-right: none !important; }
132 | .coverage-summary th.pct { }
133 | .coverage-summary th.pic,
134 | .coverage-summary th.abs,
135 | .coverage-summary td.pct,
136 | .coverage-summary td.abs { text-align: right; }
137 | .coverage-summary td.file { white-space: nowrap; }
138 | .coverage-summary td.pic { min-width: 120px !important; }
139 | .coverage-summary tfoot td { }
140 |
141 | .coverage-summary .sorter {
142 | height: 10px;
143 | width: 7px;
144 | display: inline-block;
145 | margin-left: 0.5em;
146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent;
147 | }
148 | .coverage-summary .sorted .sorter {
149 | background-position: 0 -20px;
150 | }
151 | .coverage-summary .sorted-desc .sorter {
152 | background-position: 0 -10px;
153 | }
154 | .status-line { height: 10px; }
155 | /* yellow */
156 | .cbranch-no { background: yellow !important; color: #111; }
157 | /* dark red */
158 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 }
159 | .low .chart { border:1px solid #C21F39 }
160 | .highlighted,
161 | .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{
162 | background: #C21F39 !important;
163 | }
164 | /* medium red */
165 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE }
166 | /* light red */
167 | .low, .cline-no { background:#FCE1E5 }
168 | /* light green */
169 | .high, .cline-yes { background:rgb(230,245,208) }
170 | /* medium green */
171 | .cstat-yes { background:rgb(161,215,106) }
172 | /* dark green */
173 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) }
174 | .high .chart { border:1px solid rgb(77,146,33) }
175 | /* dark yellow (gold) */
176 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; }
177 | .medium .chart { border:1px solid #f9cd0b; }
178 | /* light yellow */
179 | .medium { background: #fff4c2; }
180 |
181 | .cstat-skip { background: #ddd; color: #111; }
182 | .fstat-skip { background: #ddd; color: #111 !important; }
183 | .cbranch-skip { background: #ddd !important; color: #111; }
184 |
185 | span.cline-neutral { background: #eaeaea; }
186 |
187 | .coverage-summary td.empty {
188 | opacity: .5;
189 | padding-top: 4px;
190 | padding-bottom: 4px;
191 | line-height: 1;
192 | color: #888;
193 | }
194 |
195 | .cover-fill, .cover-empty {
196 | display:inline-block;
197 | height: 12px;
198 | }
199 | .chart {
200 | line-height: 0;
201 | }
202 | .cover-empty {
203 | background: white;
204 | }
205 | .cover-full {
206 | border-right: none !important;
207 | }
208 | pre.prettyprint {
209 | border: none !important;
210 | padding: 0 !important;
211 | margin: 0 !important;
212 | }
213 | .com { color: #999 !important; }
214 | .ignore-none { color: #999; font-weight: normal; }
215 |
216 | .wrapper {
217 | min-height: 100%;
218 | height: auto !important;
219 | height: 100%;
220 | margin: 0 auto -48px;
221 | }
222 | .footer, .push {
223 | height: 48px;
224 | }
225 |
--------------------------------------------------------------------------------
/Ejercicios/Tests/coverage/lcov-report/block-navigation.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | var jumpToCode = (function init() {
3 | // Classes of code we would like to highlight in the file view
4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no'];
5 |
6 | // Elements to highlight in the file listing view
7 | var fileListingElements = ['td.pct.low'];
8 |
9 | // We don't want to select elements that are direct descendants of another match
10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > `
11 |
12 | // Selecter that finds elements on the page to which we can jump
13 | var selector =
14 | fileListingElements.join(', ') +
15 | ', ' +
16 | notSelector +
17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b`
18 |
19 | // The NodeList of matching elements
20 | var missingCoverageElements = document.querySelectorAll(selector);
21 |
22 | var currentIndex;
23 |
24 | function toggleClass(index) {
25 | missingCoverageElements
26 | .item(currentIndex)
27 | .classList.remove('highlighted');
28 | missingCoverageElements.item(index).classList.add('highlighted');
29 | }
30 |
31 | function makeCurrent(index) {
32 | toggleClass(index);
33 | currentIndex = index;
34 | missingCoverageElements.item(index).scrollIntoView({
35 | behavior: 'smooth',
36 | block: 'center',
37 | inline: 'center'
38 | });
39 | }
40 |
41 | function goToPrevious() {
42 | var nextIndex = 0;
43 | if (typeof currentIndex !== 'number' || currentIndex === 0) {
44 | nextIndex = missingCoverageElements.length - 1;
45 | } else if (missingCoverageElements.length > 1) {
46 | nextIndex = currentIndex - 1;
47 | }
48 |
49 | makeCurrent(nextIndex);
50 | }
51 |
52 | function goToNext() {
53 | var nextIndex = 0;
54 |
55 | if (
56 | typeof currentIndex === 'number' &&
57 | currentIndex < missingCoverageElements.length - 1
58 | ) {
59 | nextIndex = currentIndex + 1;
60 | }
61 |
62 | makeCurrent(nextIndex);
63 | }
64 |
65 | return function jump(event) {
66 | switch (event.which) {
67 | case 78: // n
68 | case 74: // j
69 | goToNext();
70 | break;
71 | case 66: // b
72 | case 75: // k
73 | case 80: // p
74 | goToPrevious();
75 | break;
76 | }
77 | };
78 | })();
79 | window.addEventListener('keydown', jumpToCode);
80 |
--------------------------------------------------------------------------------
/Ejercicios/Tests/coverage/lcov-report/bracketValidator.js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Code coverage report for bracketValidator.js
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 |
19 |
//encontrar el indice de la primera aparicion de un string(needle)
120 | //dentro de otro(haystack)
121 | //no se puede utilizar indexOf()
122 |
123 | //ejemplo:
124 | //haystack = 'react-redux'
125 | //needle = 'redux'
126 | //output = 5
127 |
128 | //haystack = 'react-redux'
129 | //needle = 'hola'
130 | //output = -1
131 |
132 |
133 | module.exports = function findNeedle(haystack, needle) {
134 | // iteramos sobre el haystack
135 | for (let haystackIndex = 0; haystackIndex < haystack.length; haystackIndex += 1) {
136 | // comenzamos a iterar sobre el needle
137 | for (let needleIndex = 0; needleIndex < needle.length; needleIndex += 1 ) {
138 | // comparamos la letra del needle en la que estamos con la letra del haystack
139 | // cuando no hay match cortamos de comparar el needle
140 | if (haystack[haystackIndex + needleIndex] !== needle[needleIndex]) break;
141 | // si terminamos de recorrer la needle devolvemos el haystackIndex
142 | if (needleIndex + 1 === needle.length) return haystackIndex;
143 | }
144 | }
145 | // una vez que termina el loop devolvemos -1
146 | return -1;
147 | }
148 |
149 |