├── 26 - WtF!!!! ├── index.js └── README.md ├── README.md ├── 02 - Ayuda al elfo a listar los regalos ├── index.js └── README.md ├── 01 - Contando ovejas para dormir ├── index.js └── README.md ├── 20 - Una carta de pangramas ├── index.js └── README.md ├── 03 - El Grinch quiere fastidiar la Navidad ├── index.js └── README.md ├── 06 - Rematando los exámenes finales ├── index.js └── README.md ├── 04 - Es hora de poner la navidad en casa ├── index.js └── README.md ├── 13 - Envuelve regalos con asteriscos ├── index.js └── README.md ├── 24 - Comparando árboles de Navidad ├── index.js └── README.md ├── 11 - Vale la pena la tarjeta fidelidad del cine ├── index.js └── README.md ├── 18 - El sistema operativo de Santa Claus ├── index.js └── README.md ├── 07 - Buscando en el almacén ├── index.js └── README.md ├── 17 - La locura de enviar paquetes en esta época ├── index.js └── README.md ├── 08 - La locura de las criptomonedas ├── index.js └── README.md ├── 14 - En busca del reino perdido ├── README.md └── index.js ├── 16 - Descifrando los números ├── index.js └── README.md ├── 05 - Contando los días para los regalos ├── index.js └── README.md ├── 15 - El salto perfecto ├── index.js └── README.md ├── 09 - Agrupando cosas automáticamente ├── index.js └── README.md ├── 10 - La máquina de cambio ├── README.md └── index.js ├── 23 - Puedes reconfigurar las fábricas para no parar de crear regalos ├── index.js └── README.md ├── 12 - La ruta perfecta para dejar los regalos ├── index.js └── README.md ├── 25 - El último juego y hasta el año que viene ├── index.js └── README.md ├── 22 - Cuantos adornos necesita el árbol ├── index.js └── README.md ├── 19 - Qué deberíamos aprender en Platzi ├── index.js └── README.md └── 21 - La ruta con los regalos ├── index.js └── README.md /26 - WtF!!!!/index.js: -------------------------------------------------------------------------------- 1 | export default function devuelveMidudev() { 2 | return "midudev" 3 | } -------------------------------------------------------------------------------- /26 - WtF!!!!/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | El reto secreto. Devuelve la palabra "midudev". -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Retos de AdventJS 2 | 3 | Aquí almacenaré todos los retos de [AdventJS](https://adventjs.dev) resueltos por mí. 4 | 5 | ### ¿Qué es AdventJS? 6 | AdventJS es una iniciativa de [@midudev](https://github.com/midudev) basada en [Advent of Code](https://adventofcode.com/) que consiste en resolver un reto diario cada día de diciembre hasta el día 25. -------------------------------------------------------------------------------- /02 - Ayuda al elfo a listar los regalos/index.js: -------------------------------------------------------------------------------- 1 | function listGifts(letter){ 2 | var resultado = {} 3 | letter.split(" ") 4 | .filter(regalo => regalo.charAt(0)!== "_" && regalo!== "") 5 | .map( regalo => { 6 | resultado[regalo] = (resultado[regalo]|| 0 ) + 1 7 | }) 8 | return resultado 9 | } 10 | 11 | const carta = 'bici coche balón _playstation bici coche peluche' 12 | 13 | console.log(listGifts(carta)) -------------------------------------------------------------------------------- /01 - Contando ovejas para dormir/index.js: -------------------------------------------------------------------------------- 1 | function contarOvejas(ovejas){ 2 | return ovejas.filter( ({name, color}) => { 3 | return name.toLowerCase().includes("a") && name.toLowerCase().includes("n") && color.toLowerCase() === "rojo" 4 | }) 5 | } 6 | 7 | const ovejas = [ 8 | { name: 'Noa', color: 'azul' }, 9 | { name: 'Euge', color: 'rojo' }, 10 | { name: 'Navidad', color: 'rojo' }, 11 | { name: 'Ki Na Ma', color: 'rojo'} 12 | ] 13 | 14 | console.log(contarOvejas(ovejas)) -------------------------------------------------------------------------------- /20 - Una carta de pangramas/index.js: -------------------------------------------------------------------------------- 1 | function pangram(letter) { 2 | const abc = "abcdefghijklmnñopqrstuvwxyz".split('') 3 | letter = letter.normalize().toLowerCase(); 4 | return abc.every(character => letter.includes(character)) 5 | } 6 | 7 | console.log(pangram('Extraño pan de col y kiwi se quemó bajo fugaz vaho')) // true 8 | console.log(pangram('Jovencillo emponzoñado y con walkman: ¡qué figurota exhibe!')) // false 9 | console.log(pangram('Esto es una frase larga pero no tiene todas las letras del abecedario')) // false 10 | console.log(pangram('De la a a la z, nos faltan letras')) // false -------------------------------------------------------------------------------- /03 - El Grinch quiere fastidiar la Navidad/index.js: -------------------------------------------------------------------------------- 1 | function isValid(letter){ 2 | return letter.includes("(") 3 | && letter.includes(")") 4 | && letter.split(/[\(\)]/)[1]!== '' 5 | && letter.split(/[\(\)]/)[1].match(/(\[|\{)/)===null 6 | && letter.match(/\(/g).length === letter.match(/\)/g).length 7 | } 8 | 9 | 10 | console.log(isValid("bici coche (balón) bici coche peluche")) 11 | console.log(isValid("(muñeca) consola bici")) 12 | console.log(isValid("bici coche (balón bici coche")) 13 | console.log(isValid("peluche (bici [coche) bici coche balón")) 14 | console.log(isValid("(peluche {) bici")) 15 | console.log(isValid("() bici")) -------------------------------------------------------------------------------- /06 - Rematando los exámenes finales/index.js: -------------------------------------------------------------------------------- 1 | function sumPairs(numbers, result) { 2 | for(let actualIndex=0; actualIndex < numbers.length; actualIndex++){ 3 | let actualNum = numbers[actualIndex]; 4 | let neededNum = result - actualNum; 5 | let neededNumIndex = numbers.indexOf(neededNum) 6 | if(neededNumIndex === actualIndex) continue; 7 | if(neededNumIndex !== -1){ 8 | return [actualNum, neededNum]; 9 | } 10 | } 11 | return null; 12 | } 13 | 14 | console.log(sumPairs([3, 5, 7, 2], 10)) // [3, 7] 15 | console.log(sumPairs([-3, -2, 7, -5], 10)) // null 16 | console.log(sumPairs([2, 2, 3, 1], 4)) // [2, 2] 17 | console.log(sumPairs([6, 7, 1, 2], 8)) // [6, 2] 18 | console.log(sumPairs([0, 2, 2, 3, -1, 1, 5], 6)) // [1, 5] -------------------------------------------------------------------------------- /04 - Es hora de poner la navidad en casa/index.js: -------------------------------------------------------------------------------- 1 | function createXmasTree(height) { 2 | if(height < 1 || height > 100 || !Number.isInteger(height)) return "La altura debe estar entre 1 y 100 y ser un número entero." 3 | var tree = ""; 4 | var maxWidth = 2*(height-1)+1; 5 | // Hojas 6 | for(let i = 0; i < height; i++){ 7 | let leaves = 2*i+1; // Hojas en cada fila 8 | let spaces = (maxWidth - leaves)/2; // Espacios a los lados de cada fila del arbol 9 | tree += `${"_".repeat(spaces)}${"*".repeat(leaves)}${"_".repeat(spaces)}\n`; 10 | } 11 | // Tronco 12 | tree += `${"_".repeat((maxWidth-1)/2)}#${"_".repeat((maxWidth-1)/2)}\n` 13 | tree += `${"_".repeat((maxWidth-1)/2)}#${"_".repeat((maxWidth-1)/2)}` 14 | return tree 15 | } 16 | 17 | // 🎄 18 | console.log(createXmasTree(5)); -------------------------------------------------------------------------------- /13 - Envuelve regalos con asteriscos/index.js: -------------------------------------------------------------------------------- 1 | function wrapGifts(gifts) { 2 | return gifts.reduce((acc, gift, i) => { 3 | if (gifts.length === 0) return acc 4 | if (acc.length === 0) acc = [`*${'*'.repeat(gift.length)}*`] 5 | return gifts.length === i + 1 6 | ? [...acc, `*${gift}*`, `*${'*'.repeat(gift.length)}*`] 7 | : [...acc, `*${gift}*`] 8 | }, []) 9 | } 10 | 11 | 12 | 13 | 14 | 15 | 16 | console.log(wrapGifts(["📷", "⚽️"])) 17 | /* Resultado: 18 | [ '****', 19 | '*📷*', 20 | '*⚽️*', 21 | '****' 22 | ] 23 | */ 24 | 25 | console.log(wrapGifts(["🏈🎸", "🎮🧸"])) 26 | /* Resultado: 27 | [ '******', 28 | '*🏈🎸*', 29 | '*🎮🧸*', 30 | '******' 31 | ] 32 | */ 33 | 34 | console.log(wrapGifts(["📷"])) 35 | /* Resultado: 36 | [ '****', 37 | '*📷*', 38 | '****' 39 | ] 40 | */ -------------------------------------------------------------------------------- /24 - Comparando árboles de Navidad/index.js: -------------------------------------------------------------------------------- 1 | function checkIsSameTree(treeA, treeB) { 2 | if (!treeA && !treeB) return true 3 | if (treeA?.value !== treeB?.value) return false 4 | return checkIsSameTree(treeA.left, treeB.left) && checkIsSameTree(treeA.right, treeB.right) 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | const tree = { 17 | value: 1, 18 | left: { value: 2, left: null, right: null }, 19 | right: { value: 3, left: null, right: null } 20 | } 21 | 22 | console.log(checkIsSameTree(tree, tree)) // true 23 | 24 | const tree2 = { 25 | value: 1, 26 | left: { value: 3, left: { value: 2, left: null, right: null }, right: null }, 27 | right: { value: 5, left: null, right: { value: 4, left: null, right: null } } 28 | } 29 | 30 | console.log(checkIsSameTree(tree, tree2)) // false 31 | console.log(checkIsSameTree(tree2, tree2)) // true -------------------------------------------------------------------------------- /11 - Vale la pena la tarjeta fidelidad del cine/index.js: -------------------------------------------------------------------------------- 1 | function shouldBuyFidelity(times) { 2 | var entradaNormal = 12 * times 3 | var entradaTarjetaFidelity = 250 4 | for (let i = 1; i <= times; i++) { 5 | entradaTarjetaFidelity += 12 * 0.75**i 6 | } 7 | return entradaTarjetaFidelity < entradaNormal 8 | } 9 | 10 | function shouldBuyFidelityReduce(times){ 11 | // entradaNormal > entradaFidelity 12 | return 12*times > [...Array(times).keys()].reduce( (acc, i) => acc + 12*0.75**(i+1), 250) 13 | } 14 | 15 | 16 | 17 | console.log(shouldBuyFidelityReduce(3)) // false -> Mejor comprar tickets de un sólo uso 18 | console.log(shouldBuyFidelity(3)) // false -> Mejor comprar tickets de un sólo uso 19 | console.log(shouldBuyFidelity(1)) // false -> Mejor comprar tickets de un sólo uso 20 | console.log(shouldBuyFidelityReduce(100)) // true -> Mejor comprar tarjeta fidelidad -------------------------------------------------------------------------------- /18 - El sistema operativo de Santa Claus/index.js: -------------------------------------------------------------------------------- 1 | function fixFiles(files) { 2 | return files.map((file, i) => { 3 | const filtered = files.slice(0, i).filter(filter => file === filter) 4 | return filtered.length === 0 ? file : `${file}(${filtered.length})` 5 | }) 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | const files = ['photo', 'postcard', 'photo', 'photo', 'video'] 18 | console.log(fixFiles(files)) // ['photo', 'postcard', 'photo(1)', 'photo(2)', 'video'] 19 | 20 | const files2 = ['file', 'file', 'file', 'game', 'game'] 21 | console.log(fixFiles(files2)) // ['file', 'file(1)', 'file(2)', 'game', 'game(1)'] 22 | 23 | // ojo que los elfos ya tenían archivos con (1)... ¡y pueden estar repetidos! 24 | const files3 = ['file', 'file(1)', 'icon', 'icon(1)', 'icon(1)'] 25 | console.log(fixFiles(files3)) // ['file', 'file(1)', 'icon', 'icon(1)', 'icon(1)(1)'] -------------------------------------------------------------------------------- /07 - Buscando en el almacén/index.js: -------------------------------------------------------------------------------- 1 | function contains(store, searchProduct) { 2 | return ( 3 | typeof store === "object" 4 | ? Object.values(store).some( contenedor => contains(contenedor, searchProduct) ) 5 | : store === searchProduct 6 | ) 7 | } 8 | 9 | const almacen = { 10 | 'estanteria1': { 11 | 'cajon1': { 12 | 'producto1': 'coca-cola', 13 | 'producto2': 'fanta', 14 | 'producto3': 'sprite' 15 | } 16 | }, 17 | 'estanteria2': { 18 | 'cajon1': 'vacio', 19 | 'cajon2': { 20 | 'producto1': 'pantalones', 21 | 'producto2': 'camiseta' // <- ¡Está aquí! 22 | } 23 | } 24 | } 25 | const otroAlmacen = { 26 | 'baul': { 27 | 'fondo': { 28 | 'objeto': 'cd-rom', 29 | 'otro-objeto': 'disquette', 30 | 'otra-cosa': 'mando' 31 | } 32 | } 33 | } 34 | 35 | console.log(contains(almacen, 'camiseta')) // true 36 | console.log(contains(otroAlmacen, 'gameboy')) // false -------------------------------------------------------------------------------- /17 - La locura de enviar paquetes en esta época/index.js: -------------------------------------------------------------------------------- 1 | function countPackages(carriers, carrierID) { 2 | const carrier = carriers.filter(carrier => carrier[0] === carrierID)[0] 3 | return carrier[2].reduce((packages, subCarrier) => { 4 | return packages + countPackages(carriers, subCarrier) 5 | }, carrier[1]) 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | const carriers = [ 14 | ['dapelu', 5, ['midu', 'jelowing']], 15 | ['midu', 2, []], 16 | ['jelowing', 2, []] 17 | ] 18 | 19 | console.log(countPackages(carriers, 'dapelu')) // 9 20 | // 5 de dapelu, 2 de midu y 2 de jelowing = 9 21 | 22 | 23 | const carriers2 = [ 24 | ['lolivier', 8, ['camila', 'jesuspoleo']], 25 | ['camila', 5, ['sergiomartinez', 'conchaasensio']], 26 | ['jesuspoleo', 4, []], 27 | ['sergiomartinez', 4, []], 28 | ['conchaasensio', 3, ['facundocapua', 'faviola']], 29 | ['facundocapua', 2, []], 30 | ['faviola', 1, []] 31 | ] 32 | 33 | console.log(countPackages(carriers2, 'camila')) // 15 -------------------------------------------------------------------------------- /13 - Envuelve regalos con asteriscos/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | ¡Hay demasiados regalos 🎁! Y envolverlos es una locura... 4 | 5 | Vamos a crear una función que pasándole un array de regalos, nos devuelva otro array pero donde todos los regalos han sido envueltos con asteriscos tanto por arriba como por los lados. 6 | 7 | Sólo tienes que tener en cuenta unas cosillas ✌️: 8 | 9 | Si el array está vacío, devuelve un array vacío 10 | Los regalos son emojis 🎁... por lo que tenlo en cuenta a la hora de contar su longitud... 11 | Por suerte, cada posición del array siempre tiene la misma longitud... 12 | 13 | ```javascript 14 | wrapGifts(["📷", "⚽️"]) 15 | /* Resultado: 16 | [ '****', 17 | '*📷*', 18 | '*⚽️*', 19 | '****' 20 | ] 21 | */ 22 | 23 | wrapGifts(["🏈🎸", "🎮🧸"]) 24 | /* Resultado: 25 | [ '******', 26 | '*🏈🎸*', 27 | '*🎮🧸*', 28 | '******' 29 | ] 30 | */ 31 | 32 | wrapGifts(["📷"]) 33 | /* Resultado: 34 | [ '****', 35 | '*📷*', 36 | '****' 37 | ] 38 | */ 39 | ``` -------------------------------------------------------------------------------- /03 - El Grinch quiere fastidiar la Navidad/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | El Grinch está abriendo las cartas que iban a Santa Claus y las está dejando hechas un lío. 😱 4 | 5 | Las cartas son una cadena de texto que incluyen regalos y paréntesis `()`. 6 | 7 | Para saber si una carta es válida ✅, debes comprobar que los paréntesis cierran correctamente y que, además, no vayan vacíos. 8 | 9 | ¡Pero ojo! Porque el Grinch ha dejado llaves `{` y corchetes `[` dentro de los paréntesis que **hacen que no sean válidas**. Por suerte sólo los ha dejado en medio de los paréntesis... 10 | 11 | Ejemplos: 12 | 13 | ```javascript 14 | "bici coche (balón) bici coche peluche" // -> ✅ 15 | "(muñeca) consola bici" // ✅ 16 | 17 | "bici coche (balón bici coche" // -> ❌ 18 | "peluche (bici [coche) bici coche balón" // -> ❌ 19 | "(peluche {) bici" // -> ❌ 20 | "() bici" // ❌ 21 | ``` 22 | 23 | Crea una función que pasándole el texto de la carta, devuelva `true` si es válida y `false` si no lo es. ¡Y acaba con la travesura del Grinch! -------------------------------------------------------------------------------- /08 - La locura de las criptomonedas/index.js: -------------------------------------------------------------------------------- 1 | function maxProfit(prices) { 2 | var profit = 0; 3 | [...prices].forEach( price => { 4 | prices.shift() 5 | prices.forEach( comparePrice => { 6 | profit = ( 7 | (comparePrice - price) > profit 8 | ? comparePrice - price 9 | : profit 10 | ) 11 | }) 12 | }) 13 | return profit || -1 14 | } 15 | 16 | 17 | 18 | 19 | 20 | 21 | const pricesBtc = [39, 18, 29, 25, 34, 32, 5] 22 | console.log(maxProfit(pricesBtc)) // -> 16 (compra a 18, vende a 34) 23 | 24 | 25 | const pricesEth = [10, 20, 30, 40, 50, 60, 70] 26 | console.log(maxProfit(pricesEth)) // -> 60 (compra a 10, vende a 70) 27 | 28 | const pricesTest = [1, 1, 1] 29 | console.log(maxProfit(pricesTest)); // -> -1 (no hay ganancia posible) 30 | 31 | const pricesDoge = [18, 15, 12, 11, 9, 7] 32 | console.log(maxProfit(pricesDoge)) // -> -1 (no hay ganancia posible) 33 | 34 | const pricesAda = [3, 3, 3, 3, 3] 35 | console.log(maxProfit(pricesAda)) // -> -1 (no hay ganancia posible) -------------------------------------------------------------------------------- /04 - Es hora de poner la navidad en casa/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | ¡Es hora de poner el árbol de navidad en casa! 🎄 4 | 5 | Para ello vamos a crear una función que recibe la altura del árbol, que será un entero positivo del 1 a, como máximo, 100. 6 | 7 | Si le pasamos el argumento `5`, se pintaría esto: 8 | 9 | ```javascript 10 | ____*____ 11 | ___***___ 12 | __*****__ 13 | _*******_ 14 | ********* 15 | ____#____ 16 | ____#____ 17 | ``` 18 | 19 | Creamos un triángulo de asteríscos `*` con la altura proporcionada y, a los lados, usamos el guión bajo `_` para los espacios. Es muy importante que nuestro árbol siempre tenga la misma longitud por cada lado. 20 | Todos los árboles, por pequeños o grandes que sean, tienen un tronco de dos líneas de `#`. 21 | 22 | Otro ejemplo con un árbol de altura `3`: 23 | 24 | ```javascript 25 | __*__ 26 | _***_ 27 | ***** 28 | __#__ 29 | __#__ 30 | ``` 31 | 32 | Ten en cuenta que el árbol es un string y necesitas los saltos de línea `\n` para cada línea para que se forme bien el árbol. -------------------------------------------------------------------------------- /14 - En busca del reino perdido/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | ¡Hemos perdido a un reno y falta poco más de una semana para Navidad! 😱 4 | 5 | Lo peor es que son tantos que no sabemos cuál es el que nos falta... ¡Qué lío! A ver, _Elfon Musk_ ha hecho inventario y nos pasa un array con los ids de cada reno. 6 | 7 | 👍 **Lo bueno**: los ids son números que pueden ir del 0 al 100, no están repetidos y sólo se ha perdido un reno. 8 | 9 | 👎 **Lo malo**: la lista está desordenada y podría faltar el último... 10 | 11 | Necesitamos una función que al pasarle la lista de ids de renos nos diga inmediatamente cuál es el que falta: 12 | 13 | ```javascript 14 | missingReindeer([0, 2, 3]) // -> 1 15 | missingReindeer([5, 6, 1, 2, 3, 7, 0]) // -> 4 16 | missingReindeer([0, 1]) // -> 2 (¡es el último el que falta!) 17 | missingReindeer([3, 0, 1]) // -> 2 18 | missingReindeer([9, 2, 3, 5, 6, 4, 7, 0, 1]) // -> 8 19 | missingReindeer([0]) // -> 1 (¡es el último el que falta!) 20 | ``` 21 | 22 | Parece fácil con una complejidad de O(n)... ¿crees que podrías hacerlo mejor? -------------------------------------------------------------------------------- /01 - Contando ovejas para dormir/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Considera una lista/array de ovejas. Cada oveja tiene un nombre y un color. Haz una función que devuelva una lista con todas las ovejas que sean de color `rojo` y que además su nombre contenga tanto las letras `n` Y `a`, sin importar el orden, las mayúsculas o espacios. 4 | 5 | Por ejemplo, si tenemos las ovejas: 6 | 7 | ```javascript 8 | const ovejas = [ 9 | { name: 'Noa', color: 'azul' }, 10 | { name: 'Euge', color: 'rojo' }, 11 | { name: 'Navidad', color: 'rojo' }, 12 | { name: 'Ki Na Ma', color: 'rojo'}, 13 | { name: 'AAAAAaaaaa', color: 'rojo' }, 14 | { name: 'Nnnnnnnn', color: 'rojo'} 15 | ] 16 | ``` 17 | 18 | Al ejecutar el método debería devolver lo siguiente: 19 | 20 | ```javascript 21 | const ovejasFiltradas = contarOvejas(ovejas) 22 | 23 | console.log(ovejasFiltradas) 24 | 25 | // [{ name: 'Navidad', color: 'rojo' }, 26 | // { name: 'Ki Na Ma', color: 'rojo' }] 27 | ``` 28 | Recuerda. **Debe contener las dos letras 'a' y 'n' en el nombre**. No cuentes ovejas que sólo tenga una de las letras, debe tener ambas. -------------------------------------------------------------------------------- /16 - Descifrando los números/index.js: -------------------------------------------------------------------------------- 1 | function decodeNumbers(symbols) { 2 | const map = { 3 | '.': 1, 4 | ',': 5, 5 | ':': 10, 6 | ';': 50, 7 | '!': 100 8 | } 9 | symbols = symbols.split('').reverse(); 10 | return symbols.reduce((acc, symbol, i) => { 11 | if (isNaN(acc) || !map[symbol]) return NaN 12 | return map[symbols[i-1]] > map[symbol] ? acc - map[symbol] : acc + map[symbol] 13 | }, 0) 14 | } 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | console.log(decodeNumbers('...')) // 3 23 | console.log(decodeNumbers('.,')) // 4 (5 - 1) 24 | console.log(decodeNumbers(',.')) // 6 (5 + 1) 25 | console.log(decodeNumbers(',...')) // 8 (5 + 3) 26 | console.log(decodeNumbers('.........!')) // 107 (1 + 1 + 1 + 1 + 1 + 1 + 1 - 1 + 100) 27 | console.log(decodeNumbers('.;')) // 49 (50 - 1) 28 | console.log(decodeNumbers('..,')) // 5 (-1 + 1 + 5) 29 | console.log(decodeNumbers('..,!')) // 95 (1 - 1 - 5 + 100) 30 | console.log(decodeNumbers('.;!')) // 49 (-1 -50 + 100) 31 | console.log(decodeNumbers('!!!')) // 300 32 | console.log(decodeNumbers(';!')) // 50 33 | console.log(decodeNumbers(';.W')) // NaN -------------------------------------------------------------------------------- /05 - Contando los días para los regalos/index.js: -------------------------------------------------------------------------------- 1 | function daysToXmas(date) { 2 | const christmasDate = new Date("Dec 25, 2021") 3 | const secondsTillChristmas = christmasDate.getTime()/1000 - date.getTime()/1000 4 | const daysTillChristmas = secondsTillChristmas/60/60/24 5 | return Math.ceil(daysTillChristmas) 6 | } 7 | 8 | const date1 = new Date('Dec 1, 2021') 9 | console.log(daysToXmas(date1)) // 24 10 | const date2 = new Date('Dec 24, 2021 00:00:01') 11 | console.log(daysToXmas(date2)) // 1 12 | const date3 = new Date('Dec 24, 2021 23:59:59') 13 | console.log(daysToXmas(date3)) // 1 14 | const date4 = new Date("December 20, 2021 03:24:00") 15 | console.log(daysToXmas(date4)) // 5 16 | const date5 = new Date('Dec 25, 2021') 17 | console.log(daysToXmas(date5)) // 0 18 | const date6 = new Date('Dec 26, 2021') 19 | console.log(daysToXmas(date6)) // -1 20 | const date7 = new Date('Dec 31, 2021') 21 | console.log(daysToXmas(date7)) // -6 22 | const date8 = new Date('Jan 1, 2022 00:00:01') 23 | console.log(daysToXmas(date8)) // -7 24 | const date9 = new Date('Jan 1, 2022 23:59:59') 25 | console.log(daysToXmas(date9)) // -7 -------------------------------------------------------------------------------- /14 - En busca del reino perdido/index.js: -------------------------------------------------------------------------------- 1 | function missingReindeer(ids) { 2 | const index = ids 3 | .indexOf(ids.sort((a, b) => a - b) 4 | .filter((reno, i) => reno !== i)[0]) 5 | return index === -1 ? Math.max(...ids)+1 : index 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | console.log(missingReindeer([0, 2, 3])) // -> 1 14 | console.log(missingReindeer([5, 6, 1, 2, 3, 7, 0])) // -> 4 15 | console.log(missingReindeer([0, 1])) // -> 2 (¡es el último el que falta!) 16 | console.log(missingReindeer([3, 0, 1])) // -> 2 17 | console.log(missingReindeer([9, 2, 3, 5, 6, 4, 7, 0, 1])) // -> 8 18 | console.log(missingReindeer([0])) // -> 1 (¡es el último el que falta!) 19 | console.log(missingReindeer([0, 32, 63, 5, 62, 93, 89, 61, 39, 98, 13, 80, 22, 91, 73, 84, 60, 90, 38, 55, 65, 28, 45, 30, 71, 21, 88, 58, 81, 29, 46, 77, 64, 34, 83, 8, 1, 70, 86, 72, 2, 69, 87, 57, 97, 53, 96, 95, 42, 4, 31, 40, 3, 15, 6, 92, 43, 24, 19, 20, 67, 26, 9, 25, 47, 36, 74, 100, 12, 16, 79, 44, 59, 99, 37, 7, 75, 11, 27, 78, 23, 85, 10, 35, 76, 49, 94, 50, 56, 82, 54, 68, 52, 66, 33, 51, 17, 14, 41, 18, 48])) // -> 101 (¡es el último que falta!) -------------------------------------------------------------------------------- /06 - Rematando los exámenes finales/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Antes de poder disfrutar de la navidad... nos toca terminar de rematar los exámenes finales. ¡Y toca un poco de matemáticas! 😱 4 | 5 | A una función se le pasan dos parámetros: un Array con números y el resultado que se espera. 6 | 7 | La función debe devolver los dos valores del Array que sumen el resultado esperado. Como a veces **pueden haber más de dos valores** que sumen, se devolverá el primero empezando por la izquierda que encuentre otro par, **sin importar lo lejos que esté a la derecha**. 8 | 9 | Si no se encuentra, se devuelve `null`. 10 | 11 | Veamos unos ejemplos: 12 | 13 | ```javascript 14 | sumPairs([3, 5, 7, 2], 10) // [3, 7] 15 | sumPairs([-3, -2, 7, -5], 10) // null 16 | sumPairs([2, 2, 3, 1], 4) // [2, 2] 17 | sumPairs([6, 7, 1, 2], 8) // [6, 2] 18 | sumPairs([0, 2, 2, 3, -1, 1, 5], 6) // [1, 5] 19 | ``` 20 | 21 | El resultado tiene que ser **un array con dos números**. 22 | 23 | Una vez que tengas el resultado... ¿cómo podrías hacer que fuese lo más óptimo posible para **no tener que recorrer las mismas situaciones dos veces** 🤔? -------------------------------------------------------------------------------- /20 - Una carta de pangramas/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | En la clase de español del pueblo de Laponia han creado un reto a la hora de escribir la carta a Papa Noél 🎅: la carta ✉️ tiene que contener todas las letras del alfabeto. 4 | 5 | Desde el taller de Santa 🎅 se han enterado y quieren escribir **una función** que les diga si realmente la cadena de texto que les llega tiene, efectivamente, todas las letras del abecedario español 🔎. 6 | 7 | Hay que tener en cuenta las letras en mayúscula y que las letras con acento y diéresis se consideran iguales. Por ejemplo la `á` y la `ä` cuenta como una `a`. 8 | 9 | Vamos a ver unos ejemplos de frases: 10 | 11 | ```javascript 12 | pangram('Extraño pan de col y kiwi se quemó bajo fugaz vaho') // true 13 | pangram('Jovencillo emponzoñado y con walkman: ¡qué figurota exhibe!') // true 14 | 15 | pangram('Esto es una frase larga pero no tiene todas las letras del abecedario') // false 16 | pangram('De la a a la z, nos faltan letras') // false 17 | ``` 18 | 19 | Y ya que estás... **¿Cuál es tu pangrama favorito?** ¡Compártelo en nuestra comunidad de [Discord](https://discord.gg/midudev)! -------------------------------------------------------------------------------- /02 - Ayuda al elfo a listar los regalos/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Te ha llegado una carta ✉️ con todos los regalos que debes preparar. El tema es que es una cadena de texto y es muy difícil de leer 😱. ¡Menos mal que han puesto cada regalo separado por espacio! (aunque **ten cuidado**, porque al ser niños, igual han colado más espacios de la cuenta) 4 | 5 | Encima nos hemos dado cuenta que algunas palabras vienen con un `_` delante de la palabra, por ejemplo `_playstation`, que significa que está **tachado y no se tiene que contar.** 6 | 7 | Transforma el texto a un objeto que contenga el nombre de cada regalo y las veces que aparece. Por ejemplo, si tenemos el texto: 8 | 9 | ```javascript 10 | const carta = 'bici coche balón _playstation bici coche peluche' 11 | ``` 12 | 13 | Al ejecutar el método debería devolver lo siguiente: 14 | 15 | ```javascript 16 | const regalos = listGifts(carta) 17 | 18 | console.log(regalos) 19 | /* 20 | { 21 | bici: 2, 22 | coche: 2, 23 | balón: 1, 24 | peluche: 1 25 | } 26 | */ 27 | ``` 28 | 29 | Ten en cuenta que los tests pueden ser más exhaustivos... 😝 **¡Cuidado con contar espacios vacíos!** -------------------------------------------------------------------------------- /15 - El salto perfecto/index.js: -------------------------------------------------------------------------------- 1 | function checkSledJump(heights) { 2 | const max = { 3 | value: Math.max(...heights), 4 | index: heights.indexOf(Math.max(...heights)) 5 | }; 6 | var sube = false; 7 | var baja = false; 8 | var lastHeight = null; 9 | for (let i = 0; i < heights.length; i++) { 10 | const height = heights[i] 11 | if (height === lastHeight) return false 12 | if (i > max.index) { 13 | baja = true 14 | if (lastHeight < height) return false 15 | } 16 | sube = true 17 | lastHeight = height 18 | } 19 | return sube && baja 20 | } 21 | 22 | 23 | 24 | 25 | console.log(checkSledJump([1, 2, 3, 2, 1])) // true: sube y baja de forma estricta 26 | console.log(checkSledJump([0, 1, 0])) // -> true: sube y baja de forma estricta 27 | console.log(checkSledJump([0, 3, 2, 1])) // -> true: sube y baja de forma estricta 28 | console.log(checkSledJump([0, 1000, 1])) // -> true: sube y baja de forma estricta 29 | console.log(checkSledJump([2, 4, 4, 6, 2])) // false: no sube de forma estricta 30 | console.log(checkSledJump([1, 2, 3])) // false: sólo sube 31 | console.log(checkSledJump([1, 2, 3, 2, 1, 2, 3])) // false: sube y baja y sube... ¡no vale! -------------------------------------------------------------------------------- /11 - Vale la pena la tarjeta fidelidad del cine/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Este mes de diciembre hay películas super interesantes en el cine... y tengo que optimizar cómo gasto el dinero. 4 | 5 | Mi cine favorito tiene dos posibilidades: 6 | 7 | - Entrada de un sólo uso: Cuesta 12$ por cada película. 8 | - Tarjeta de fidelidad: Cuesta 250$ pero que cada vez que vas **pagas sólo el 75% del precio del ticket**. ¡Lo mejor es que se acumula! Y cada vez que vas, se paga el 75% del precio del ticket que pagaste la última vez. 9 | Ejemplo de cada una al comprar 3 entradas y el precio que pagaría en total: 10 | 11 | ```javascript 12 | // Entrada normal: 12$ * 3 = 36$ 13 | // Tarjeta fidelidad: 250$ + (12$ * 0,75) + (12$ * 0,75 * 0,75) + (12$ * 0,75 * 0,75 * 0,75) = 270,8125$ 14 | ``` 15 | 16 | Necesito una función que, al pasarle las veces que voy a ir al cine, me diga si vale la pena comprar la tarjeta fidelidad o no. 17 | 18 | ```javascript 19 | shouldBuyFidelity(1) // false -> Mejor comprar tickets de un sólo uso 20 | shouldBuyFidelity(100) // true -> Mejor comprar tarjeta fidelidad 21 | ``` 22 | 23 | La dificultad del reto está en encontrar una fórmula sencilla que nos diga el precio con descuento acumulado para la tarjeta fidelidad. 😜 -------------------------------------------------------------------------------- /09 - Agrupando cosas automáticamente/index.js: -------------------------------------------------------------------------------- 1 | function groupBy(collection, criteria) { 2 | return collection.reduce( (obj, item) => { 3 | let index = typeof criteria === "function" ? criteria(item) : item[criteria] // El index cambia según el tipo de criterio que se recibe 4 | return { 5 | ...obj, 6 | [index]: [...(obj[index] || []), item] 7 | }; // Devolver objeto añadiendo los resultados anteriores 8 | }, {}) 9 | } 10 | 11 | 12 | 13 | 14 | 15 | console.log(groupBy([6.1, 4.2, 6.3], Math.floor)); // { 6: [6.1, 6.3], 4: [4.2] } 16 | console.log(groupBy(['one', 'two', 'three'], 'length')) // { 3: ['one', 'two'], 5: ['three'] } 17 | console.log(groupBy([{age: 23}, {age: 24}], 'age')) // { 23: [{age: 23}], 24: [{age: 24}] } 18 | 19 | console.log(groupBy( [1397639141184, 1363223700000], timestamp => new Date(timestamp).getFullYear())) // { 2013: [1363223700000], 2014: [1397639141184] } 20 | 21 | console.log(groupBy([ 22 | { title: 'JavaScript: The Good Parts', rating: 8 }, 23 | { title: 'Aprendiendo Git', rating: 10 }, 24 | { title: 'Clean Code', rating: 9 }, 25 | ], 'rating')) 26 | // { 8: [{ title: 'JavaScript: The Good Parts', rating: 8 }], 27 | // 9: [{ title: 'Clean Code', rating: 9 }], 28 | // 10: [{ title: 'Aprendiendo Git', rating: 10 }] } -------------------------------------------------------------------------------- /08 - La locura de las criptomonedas/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Invertir en criptomonedas es casi un deporte de riesgo. El otro día hackearon Bitmart y ha hecho que el valor de Bitcoin, y otras monedas, bajase un 25%. 4 | 5 | Vamos a escribir una función que reciba la lista de precios de una criptomoneda en un día y debemos devolver la ganancia máxima que podríamos sacar si compramos y vendemos la inversión el mismo día. 6 | 7 | La lista de precios es un array de números y representa el tiempo de izquierda a derecha. Por lo que ten en cuenta que **no puedes comprar a un precio que esté a la derecha de la venta y no puedes vender a un precio que esté a la izquierda de la compra.** 8 | 9 | Por ejemplo: 10 | 11 | ```javascript 12 | const pricesBtc = [39, 18, 29, 25, 34, 32, 5] 13 | maxProfit(pricesBtc) // -> 16 (compra a 18, vende a 34) 14 | 15 | const pricesEth = [10, 20, 30, 40, 50, 60, 70] 16 | maxProfit(pricesEth) // -> 60 (compra a 10, vende a 70) 17 | ``` 18 | 19 | **Si ese día no se puede sacar ningún beneficio**, tenemos que devolver `-1` para evitar que hagamos una locura: 20 | 21 | ```javascript 22 | const pricesDoge = [18, 15, 12, 11, 9, 7] 23 | maxProfit(pricesDoge) = // -> -1 (no hay ganancia posible) 24 | 25 | const pricesAda = [3, 3, 3, 3, 3] 26 | maxProfit(pricesAda) = // -> -1 (no hay ganancia posible) 27 | ``` -------------------------------------------------------------------------------- /24 - Comparando árboles de Navidad/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | 4 | El abuelo 👴 dice que ve todos los árboles de navidad iguales... La abuela 👵, en cambio, piensa que no. Que todos los árboles de navidad son distintos... 5 | 6 | Vamos a hacer una función que nos diga si dos árboles de navidad son iguales. Para ello, vamos a comparar [los árboles que ya creamos en el reto 22](https://adventjs.dev/challenges/22). 7 | 8 | Tenemos que ver si ambos árboles tienen la misma estructura y los mismos valores en todas las ramas. Aquí tienes unos ejemplos: 9 | 10 | ```javascript 11 | const tree = { 12 | value: 1, 13 | left: { value: 2, left: null, right: null }, 14 | right: { value: 3, left: null, right: null } 15 | } 16 | 17 | checkIsSameTree(tree, tree) // true 18 | 19 | const tree2 = { 20 | value: 1, 21 | left: { value: 3, left: { value: 2, left: null, right: null }, right: null }, 22 | right: { value: 5, left: null, right: { value: 4, left: null, right: null } } 23 | } 24 | 25 | checkIsSameTree(tree, tree2) // false 26 | checkIsSameTree(tree2, tree2) // true 27 | ``` 28 | 29 | El cuñado 🦹‍♂️, que se las sabe todas, me ha dicho que tenga cuidado porque **el truco del JSON.stringify puede no funcionar...** ya que los árboles pueden ser el mismo pero el orden de representación de las ramas izquierda y derecha puede ser inversa... -------------------------------------------------------------------------------- /07 - Buscando en el almacén/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Mi amigo Dani está trabajando en una tienda y con la llegada de las navidades tiene el almacén hecho un desastre y no encuentra nada. 4 | 5 | Vamos a crear una función `contains` que recibe dos parámetros: un objeto que define el almacén y el producto que buscamos. 6 | 7 | La función debe devolver un booleano que indique si se encuentra el string como valor en algún nivel del objeto. Veamos unos ejemplos: 8 | 9 | ```javascript 10 | const almacen = { 11 | 'estanteria1': { 12 | 'cajon1': { 13 | 'producto1': 'coca-cola', 14 | 'producto2': 'fanta', 15 | 'producto3': 'sprite' 16 | } 17 | }, 18 | 'estanteria2': { 19 | 'cajon1': 'vacio', 20 | 'cajon2': { 21 | 'producto1': 'pantalones', 22 | 'producto2': 'camiseta' // <- ¡Está aquí! 23 | } 24 | } 25 | } 26 | contains(almacen, 'camiseta') // true 27 | 28 | const otroAlmacen = { 29 | 'baul': { 30 | 'fondo': { 31 | 'objeto': 'cd-rom', 32 | 'otro-objeto': 'disquette', 33 | 'otra-cosa': 'mando' 34 | } 35 | } 36 | } 37 | 38 | contains(otroAlmacen, 'gameboy') // false 39 | ``` 40 | 41 | Ten en cuenta que la tienda es enorme. Tiene diferentes almacenes y, como has visto en los ejemplos, cada uno puede tener diferentes organizaciones. **Lo importante es buscar que el producto está en los almacénes.** -------------------------------------------------------------------------------- /10 - La máquina de cambio/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Para mejorar la productividad de la tienda en la que trabajamos, vamos a crear una pequeña máquina que calcula el mínimo número de monedas que debemos usar para dar el cambio de una compra en metálico. 4 | 5 | Las monedas para cambio que puedes usar son estas: 6 | 7 | ```javascript 8 | coins[0] = 1 céntimo 9 | coins[1] = 2 céntimos 10 | coins[2] = 5 céntimos 11 | coins[3] = 10 céntimos 12 | coins[4] = 20 céntimos 13 | coins[5] = 50 céntimos 14 | ``` 15 | 16 | Tenemos que crear una función que recibe el número de céntimos que hay que devolver al cliente y la función nos da un array con la **combinación de monedas mínimas** que debemos usar para conseguirlo. 17 | 18 | ```javascript 19 | getCoins(51) // [1, 0, 0, 0, 0, 1] -> una moneda de 1 céntimo y otra de 50 céntimos 20 | getCoins(3) // [1, 1, 0, 0, 0, 0] -> una moneda de 1 céntimo y otra de 2 21 | getCoins(5) // [0, 0, 1, 0, 0, 0] -> una moneda de 5 céntimos 22 | getCoins(16) // [1, 0, 1, 1, 0, 0] -> una moneda de 1 céntimo, una de 5 y una de 10 23 | getCoins(100) // [0, 0, 0, 0, 0, 2] -> dos monedas de 50 céntimos 24 | ``` 25 | 26 | La dificultad del reto está en saber utilizar correctamente una estructura que te permita conocer las monedas que tienes disponible para crear el array con la devolución, ya que **debes usar siempre el menor número de monedas posible**. ¡Suerte 👩‍💻👨‍💻!. -------------------------------------------------------------------------------- /16 - Descifrando los números/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | ara Eloft ha encontrado unos restos élficos en una cueva, cerca del Círculo Polar Ártico, a 8 km al norte de Rovaniemi. 4 | 5 | Ahora se encuentra descifrando unas misteriosas cartas que contiene información sobre unos números que le puede hacer llegar al próximo objetivo. 6 | 7 | Lara tiene un documento que contiene una serie de números que pueden ser usados para descifrarlos: 8 | 9 | ``` 10 | Símbolo Valor 11 | . 1 12 | , 5 13 | : 10 14 | ; 50 15 | ! 100 16 | ``` 17 | Lara, además, ha notado una cosa. **Los símbolos se restan si están inmediatamente a la izquierda de otro mayor. 😱** 18 | 19 | Tenemos que crear una función que nos pasa una cadena de texto con símbolos y tenemos que transformarlo al número correcto. ¡Ojo! Si encuentras un símbolo que no entendemos, mejor que devolvamos un `NaN`: 20 | 21 | ```javascript 22 | decodeNumbers('...') // 3 23 | decodeNumbers('.,') // 4 (5 - 1) 24 | decodeNumbers(',.') // 6 (5 + 1) 25 | decodeNumbers(',...') // 8 (5 + 3) 26 | decodeNumbers('.........!') // 107 (1 + 1 + 1 + 1 + 1 + 1 + 1 - 1 + 100) 27 | decodeNumbers('.;') // 49 (50 - 1) 28 | decodeNumbers('..,') // 5 (-1 + 1 + 5) 29 | decodeNumbers('..,!') // 95 (1 - 1 - 5 + 100) 30 | decodeNumbers('.;!') // 49 (-1 -50 + 100) 31 | decodeNumbers('!!!') // 300 32 | decodeNumbers(';!') // 50 33 | decodeNumbers(';.W') // NaN 34 | ``` -------------------------------------------------------------------------------- /18 - El sistema operativo de Santa Claus/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción 2 | 3 | Evelyn Belefzin 👩‍💻 está trabajando en **un sistema operativo** para ser usado en el taller de Santa Claus 🎅. 4 | 5 | Se ha dado cuenta que en el taller nadie le presta atención a los nombres de los ficheros y a veces intentan guardar el mismo fichero más de una vez... así que es importante que **gestionemos bien los nombres duplicados**. 6 | 7 | Tenemos que crear **una función que al pasarnos un array de nombres de archivo** devolvamos un array con el mismo número de elementos pero donde los nombres que se repetían se anexe al final `(k)` donde k sería el número de veces que se encontró repetido. 8 | 9 | Lo mejor es que veamos un ejemplo: 10 | 11 | ```javascript 12 | const files = ['photo', 'postcard', 'photo', 'photo', 'video'] 13 | fixFiles(files) // ['photo', 'postcard', 'photo(1)', 'photo(2)', 'video'] 14 | 15 | const files2 = ['file', 'file', 'file', 'game', 'game'] 16 | fixFiles(files2) = ['file', 'file(1)', 'file(2)', 'game', 'game(1)'] 17 | 18 | // ojo que los elfos ya tenían archivos con (1)... ¡y pueden estar repetidos! 19 | const files3 = ['file', 'file(1)', 'icon', 'icon(1)', 'icon(1)'] 20 | fixFiles(files3) // ['file', 'file(1)', 'icon', 'icon(1)', 'icon(1)(1)'] 21 | ``` 22 | 23 | Por cierto, **nos han dicho que son Agile y usan Scrum**. Por eso quieren saber cuánto tiempo vas a tardar para saber cuándo van a poder usarlo. Que hay prisa. 😝 Así que entra a Discord y cuéntanos. -------------------------------------------------------------------------------- /23 - Puedes reconfigurar las fábricas para no parar de crear regalos/index.js: -------------------------------------------------------------------------------- 1 | function canReconfigure(from, to) { 2 | if (from.length !== to.length) return false 3 | const assign = {} 4 | for (const i in from) { 5 | if (Object.values(assign).some(value => value === to[i]) && assign[from[i]]!==to[i]) return false 6 | if (assign[from[i]] && assign[from[i]] !== to[i]) return false 7 | assign[from[i]] = to[i] 8 | } 9 | return true 10 | } 11 | 12 | var from = 'BAL' 13 | var to = 'LIB' 14 | console.log(canReconfigure(from, to)) // true 15 | /* la transformación sería así: 16 | B -> L 17 | A -> I 18 | L -> B 19 | */ 20 | 21 | from = 'CON' 22 | to = 'JUU' 23 | console.log(canReconfigure(from, to)) // false 24 | /* no se puede hacer la transformación: 25 | C -> J 26 | O -> U 27 | N -> FALLO 28 | */ 29 | 30 | from = 'MMM' 31 | to = 'MID' 32 | console.log(canReconfigure(from, to)) // false 33 | /* no se puede hacer la transformación: 34 | M -> M (BIEN, asigna el mismo carácter a si mismo) 35 | M -> I (FALLO, asigna el mismo carácter a dos letras distintas) 36 | M -> D (FALLO, asigna el mismo carácter a dos letras distintas) 37 | */ 38 | 39 | from = 'AA' 40 | to = 'MID' 41 | console.log(canReconfigure(from, to)) // false -> no tiene la misma longitud 42 | 43 | from = 'aaaDDDmmm' 44 | to = 'aaaDDDmmm' 45 | console.log(canReconfigure(from, to)) // false -> no tiene la misma longitud 46 | 47 | from = 'xxxMMM' 48 | to = 'aaaDDD' 49 | console.log(canReconfigure(from, to)) -------------------------------------------------------------------------------- /15 - El salto perfecto/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | ¡Estamos haciendo los últimos ajustes para el trineo de Santa Claus! 4 | 5 | Como ya sabes, el trineo es volador y estamos ajustando el motor para que haga parabolas lo más óptimas posibles. Para esto el salto debe ser siempre hacia arriba y, a partir del punto más alto, debe bajar siempre hacia abajo... 6 | 7 | Nuestro mecánico de confianza, **Kiko Belfs**, que tiene un Tesla genial, nos ha explicado que los saltos se pueden ver como arrays... y que sólo tenemos que asegurarnos que **los números suben y bajan de forma correcta**. También nos avisa que sólo pasaremos **arrays de, como mínimo, tres posiciones**. 8 | 9 | Nos ha pasado algunos ejemplos de cómo debería ser nuestra función y algunos resultados: 10 | 11 | ```javascript 12 | checkSledJump([1, 2, 3, 2, 1]) // true: sube y baja de forma estricta 13 | checkSledJump([0, 1, 0]) // -> true: sube y baja de forma estricta 14 | checkSledJump([0, 3, 2, 1]) // -> true: sube y baja de forma estricta 15 | checkSledJump([0, 1000, 1]) // -> true: sube y baja de forma estricta 16 | 17 | checkSledJump([2, 4, 4, 6, 2]) // false: no sube de forma estricta 18 | checkSledJump([1, 2, 3]) // false: sólo sube 19 | checkSledJump([1, 2, 3, 2, 1, 2, 3]) // false: sube y baja y sube... ¡no vale! 20 | ``` 21 | 22 | Lo importante: recorrer el array de izquierda a derecha para ver que la subida es siempre estricta, detectar el punto más alto y entonces ver que la bajada es estricta hacia abajo... -------------------------------------------------------------------------------- /12 - La ruta perfecta para dejar los regalos/index.js: -------------------------------------------------------------------------------- 1 | function getMinJump(obstacles) { 2 | var jump = 1; 3 | for (let i = 0; i <= Math.max(...obstacles); i = i+jump) { 4 | if(obstacles.includes(i)){ 5 | i = 0; 6 | jump++ 7 | } 8 | } 9 | return jump 10 | } 11 | 12 | function getMinJump2(obstacles){ 13 | if(obstacles.length === 0) return 1 14 | for (let jump = 2; jump <= Math.max(...obstacles)+1; jump++) { 15 | if(obstacles.every(obstacle => obstacle % jump !== 0)){ 16 | return jump 17 | } 18 | } 19 | } 20 | 21 | var obstacles = [5, 3, 6, 7, 9] 22 | console.log(getMinJump2(obstacles)) // -> 4 23 | 24 | obstacles = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 25 | console.log(getMinJump2(obstacles)) // -> 11 26 | 27 | // S es salto, X es obstáculo 28 | /* Así quedaría la representación: 29 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 30 | . . . X . X X X . X . 31 | S-----------S-----------S------- 32 | */ 33 | 34 | obstacles = [2, 4, 6, 8, 10] 35 | console.log(getMinJump2(obstacles)) // -> 7 36 | 37 | /* Así quedaría la representación: 38 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 39 | . . X . X . X . X . X 40 | S--------------------S--------- 41 | 42 | // Longitudes de salto: 43 | // 1 caería en el 2 44 | // 2 caería en el 2 45 | // 3 caería en el 6 46 | // 4 caería en el 4 47 | // 5 caería en el 10 48 | // 6 caería en el 6 49 | // 7 es el ideal!!! ✅ 50 | 51 | getMinJump([1, 2, 3, 5]) // -> 4 52 | getMinJump([3, 7, 5]) // -> 2 53 | getMinJump([9, 5, 1]) // -> 2 54 | */ -------------------------------------------------------------------------------- /05 - Contando los días para los regalos/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Con la emoción, ya estamos empezando a **contar los días del calendario hasta el 25 de diciembre 📆.** 4 | 5 | Para ayudar a esto, vamos a crear una función que pasándole una instancia de `Date` nos diga el número de días que faltan. 6 | 7 | Veamos unos ejemplos: 8 | 9 | ```javascript 10 | const date1 = new Date('Dec 1, 2021') 11 | daysToXmas(date1) // 24 12 | const date2 = new Date('Dec 24, 2021 00:00:01') 13 | daysToXmas(date2) // 1 14 | const date3 = new Date('Dec 24, 2021 23:59:59') 15 | daysToXmas(date3) // 1 16 | const date4 = new Date("December 20, 2021 03:24:00") 17 | daysToXmas(date4) // 5 18 | ``` 19 | 20 | El resultado tiene que ser **un número entero** y, como ves, aunque falte un segundo hasta el siguiente día, se entiende que todavía falta un día. 21 | 22 | **¡Pero ojo!** También hay que indicar si la fecha es del mismo día (devolveríamos `0`) o si es una fecha futura (devolveríamos el número de días en negativo `-`): 23 | 24 | ```javascript 25 | const date = new Date('Dec 25, 2021') 26 | daysToXmas(date) // 0 27 | const date1 = new Date('Dec 26, 2021') 28 | daysToXmas(date1) // -1 29 | const date2 = new Date('Dec 31, 2021') 30 | daysToXmas(date2) // -6 31 | const date3 = new Date('Jan 1, 2022 00:00:01') 32 | daysToXmas(date3) // -7 33 | const date4 = new Date('Jan 1, 2022 23:59:59') 34 | daysToXmas(date4) // -7 35 | ``` 36 | 37 | Por cierto, la fecha de referencia para saber si es 25 de diciembre es `Dec 25, 2021`. -------------------------------------------------------------------------------- /23 - Puedes reconfigurar las fábricas para no parar de crear regalos/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Estamos en la fábrica de Santa Claus 🎅 creando regalos como si no hubiera un mañana 4 | 5 | Pensábamos que no íbamos a llegar pero **Jelf Bezos** ha tenido una idea genial para aprovechar las máquinas y optimizar al máximo la creación de regalos. 🎁 6 | 7 | La configuración de las máquinas es un string. Podemos reconfigurarla para que haga otro regalo y, para ello, podemos cambiar cada carácter por otro. 8 | 9 | Pero **tiene limitaciones** 🥲: al reemplazar el carácter se debe mantener el orden, no se puede asignar al mismo carácter a dos letras distintas (pero sí a si mismo) y, claro, la longitud del string debe ser el mismo. 10 | 11 | Necesitamos **una función que nos diga si podemos reconfigurar una máquina para que de un regalo pueda pasar a fabricar otro según las reglas** mencionadas. Lo mejor es que veamos un ejemplo: 12 | 13 | ```javascript 14 | const from = 'BAL' 15 | const to = 'LIB' 16 | const canReconfigure(from, to) // true 17 | /* la transformación sería así: 18 | B -> L 19 | A -> I 20 | L -> B 21 | */ 22 | 23 | const from = 'CON' 24 | const to = 'JUU' 25 | const canReconfigure(from, to) // false 26 | /* no se puede hacer la transformación: 27 | C -> J 28 | O -> U 29 | N -> FALLO 30 | */ 31 | 32 | const from = 'MMM' 33 | const to = 'MID' 34 | cons canReconfigure(from, to) // false 35 | /* no se puede hacer la transformación: 36 | M -> M (BIEN, asigna el mismo carácter a si mismo) 37 | ``` -------------------------------------------------------------------------------- /25 - El último juego y hasta el año que viene/index.js: -------------------------------------------------------------------------------- 1 | function canMouseEat(direction, game) { 2 | const mousePosition = game.reduce((position, row, i) => { 3 | const x = row.indexOf('m') 4 | return x === -1 ? position : {x: x, y: i} 5 | }, {}) 6 | const targetPosition = {...mousePosition}; 7 | if (direction === 'up' && mousePosition.y !== 0) targetPosition.y = mousePosition.y - 1 8 | if (direction === 'down' && mousePosition.y !== game.length - 1) targetPosition.y = mousePosition.y + 1 9 | if (direction === 'left' && mousePosition.x !== 0) targetPosition.x = mousePosition.x - 1 10 | if (direction === 'right' && mousePosition.x !== game[0].length - 1) targetPosition.x = mousePosition.x + 1 11 | if(game[targetPosition.y][targetPosition.x] === '*') return true 12 | return false 13 | } 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | const room = [ 22 | [' ', ' ', ' '], 23 | [' ', ' ', 'm'], 24 | [' ', ' ', '*'] 25 | ] 26 | 27 | console.log(canMouseEat('up', room)) // false 28 | console.log(canMouseEat('down', room)) // true 29 | console.log(canMouseEat('right', room)) // false 30 | console.log(canMouseEat('left', room)) // false 31 | 32 | const room2 = [ 33 | ['*', ' ', ' ', ' '], 34 | [' ', 'm', '*', ' '], 35 | [' ', ' ', ' ', ' '], 36 | [' ', ' ', ' ', '*'] 37 | ] 38 | 39 | console.log(canMouseEat('up', room2)) // false 40 | console.log(canMouseEat('down', room2)) // false 41 | console.log(canMouseEat('right', room2)) // true 42 | console.log(canMouseEat('left', room2)) // false -------------------------------------------------------------------------------- /09 - Agrupando cosas automáticamente/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | En la fábrica de Papa Noél 🎅 se acerca el día especial... y todavía tenemos un montón de cosas por contar. 😅 4 | 5 | Por suerte a **Mark Zucktheelf** 🧝 se le ha ocurrido crear una función que permita agrupar una colección, que puede ser un array o un objeto, a través de una función o de una propiedad. 6 | 7 | Nos trae un montón de **ejemplos**: 8 | 9 | ```javascript 10 | groupBy([6.1, 4.2, 6.3], Math.floor) // { 6: [6.1, 6.3], 4: [4.2] } 11 | groupBy(['one', 'two', 'three'], 'length') // { 3: ['one', 'two'], 5: ['three'] } 12 | groupBy([{age: 23}, {age: 24}], 'age') // { 23: [{age: 23}], 24: [{age: 24}] } 13 | 14 | groupBy( 15 | [1397639141184, 1363223700000], 16 | timestamp => new Date(timestamp).getFullYear() 17 | ) 18 | // { 2013: [1363223700000], 2014: [1397639141184] } 19 | 20 | groupBy([ 21 | { title: 'JavaScript: The Good Parts', rating: 8 }, 22 | { title: 'Aprendiendo Git', rating: 10 }, 23 | { title: 'Clean Code', rating: 9 }, 24 | ], 'rating') 25 | // { 8: [{ title: 'JavaScript: The Good Parts', rating: 8 }], 26 | // 9: [{ title: 'Clean Code', rating: 9 }], 27 | // 10: [{ title: 'Aprendiendo Git', rating: 10 }] } 28 | ``` 29 | 30 | Como ves, la función `groupBy` recibe un array y una función o una propiedad, y devuelve un objeto con claves que son los valores de la función ejecutada pasando como argumento cada elemento o de la propiedad por cada elemento. Luego los valores son un array de los valores que tengan la misma llave. 31 | 32 | La dificultad del reto está más en **comprender** la función que en la **implementación**. ¡Suerte!. -------------------------------------------------------------------------------- /25 - El último juego y hasta el año que viene/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Ayer, en noche buena, una família cenó por todo lo alto... Con tanta copa 🍾 encima todavía no han retirado los platos y la comida de ayer... 4 | 5 | Un ratoncillo llamado `midurat` 🐭, que vió ayer el festín escondido, está relamiéndose los bigotes al ver todos los manjares que hay en el comedor. 6 | 7 | Eso sí, hay que tener cuidado 😶 y sólo hacer los movimientos correctos para comer algo. Por eso, el ratón, que se ha visto [los vídeos de midudev](htts://midu.tube), va a crear una función para saber si su próximo movimiento es correcto o no ✅. 8 | 9 | El ratoncillo se puede mover en 4 direcciones: _up_, _down_, _left_, _right_ y el comedor es una matriz (un array de arrays) donde cada posición puede ser: 10 | 11 | - Un espacio vacío es que no hay nada 12 | - Una `m` es el ratón 13 | - Un `*` es la comida 14 | 15 | Vamos a ver unos ejemplos: 16 | 17 | ```javascript 18 | const room = [ 19 | [' ', ' ', ' '], 20 | [' ', ' ', 'm'], 21 | [' ', ' ', '*'] 22 | ] 23 | 24 | canMouseEat('up', room) // false 25 | canMouseEat('down', room) // true 26 | canMouseEat('right', room) // false 27 | canMouseEat('left', room) // false 28 | 29 | const room2 = [ 30 | ['*', ' ', ' ', ' '], 31 | [' ', 'm', '*', ' '], 32 | [' ', ' ', ' ', ' '], 33 | [' ', ' ', ' ', '*'] 34 | ] 35 | 36 | canMouseEat('up', room2) // false 37 | canMouseEat('down', room2) // false 38 | canMouseEat('right', room2) // true 39 | canMouseEat('left', room2) // false 40 | ``` 41 | 42 | ¡Ten en cuenta que el ratón quiere buscar comida en diferentes habitaciones y que cada una puede tener dimensiones diferentes! -------------------------------------------------------------------------------- /22 - Cuantos adornos necesita el árbol/index.js: -------------------------------------------------------------------------------- 1 | function countDecorations(bigTree) { 2 | return Object.values(bigTree).reduce((totalBranches, branch) => { 3 | if (branch === null) return totalBranches 4 | return !isNaN(branch) ? totalBranches + branch : totalBranches + countDecorations(branch) 5 | }, 0) 6 | } 7 | 8 | 9 | 10 | 11 | 12 | 13 | // tenemos el árbol en forma de objeto 14 | const tree = { 15 | value: 1, // el nodo raíz siempre es uno, porque es la estrella ⭐ 16 | left: { 17 | value: 2, // el nodo izquierdo necesita dos decoraciones 18 | left: null, // no tiene más ramas 19 | right: null // no tiene más ramas 20 | }, 21 | right: { 22 | value: 3, // el nodo de la derecha necesita tres decoraciones 23 | left: null, // no tiene más ramas 24 | right: null // no tiene más ramas 25 | } 26 | } 27 | 28 | /* Gráficamente sería así: 29 | 1 30 | / \ 31 | 2 3 32 | 33 | 1 + 2 + 3 = 6 34 | */ 35 | 36 | console.log(countDecorations(tree)) // 6 37 | 38 | // const bigTree = { 39 | // value: 1, 40 | // left: { 41 | // value: 5, 42 | // left: { 43 | // value: 7, 44 | // left: { 45 | // value: 3, 46 | // left: null, 47 | // right: null 48 | // }, 49 | // right: null 50 | // }, 51 | // right: null 52 | // }, 53 | // right: { 54 | // value: 6, 55 | // left: { 56 | // value: 5, 57 | // left: null, 58 | // right: null 59 | // }, 60 | // right: { 61 | // value: 1, 62 | // left: null, 63 | // right: null 64 | // } 65 | // } 66 | // } 67 | 68 | // /* 69 | // 1 70 | // / \ 71 | // 5 6 72 | // / / \ 73 | // 7 5 1 74 | // / 75 | // 3 76 | // */ 77 | 78 | // countDecorations(bigTree) // 28 -------------------------------------------------------------------------------- /12 - La ruta perfecta para dejar los regalos/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | En el taller de Santa 🎅 se están preparando los trineos de motor eléctrico para poder hacer la ruta perfecta para dejar los regalos. 4 | 5 | **La ruta empieza en el punto 0 y de ahí va hacia la derecha en línea recta.** 6 | 7 | El Keanu Relfes 🧝 nos ha preparado una lista de obstáculos a evitar. El problema es que nos ha dado la **lista de posiciones de los obstáculos desordenada**... 😅 aunque al menos nunca **la posición 0 puede tener un obstáculo.** 8 | 9 | Encima, el trineo sólo se puede configurar para saltar un número fijo de posiciones... 😱 10 | 11 | Necesitamos una función que nos diga la longitud mínima del salto del trineo para ir evitando todos los obstáculos en la ruta. 12 | 13 | ```javascript 14 | const obstacles = [5, 3, 6, 7, 9] 15 | getMinJump(obstacles) // -> 4 16 | 17 | // S es salto, X es obstáculo 18 | /* Así quedaría la representación: 19 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 20 | . . . X . X X X . X . 21 | S-----------S-----------S------- 22 | */ 23 | 24 | const obstacles = [2, 4, 6, 8, 10] 25 | getMinJump(obstacles) // -> 7 26 | 27 | /* Así quedaría la representación: 28 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 29 | . . X . X . X . X . X 30 | S--------------------S--------- 31 | 32 | // Longitudes de salto: 33 | // 1 caería en el 2 34 | // 2 caería en el 2 35 | // 3 caería en el 6 36 | // 4 caería en el 4 37 | // 5 caería en el 10 38 | // 6 caería en el 6 39 | // 7 es el ideal!!! ✅ 40 | 41 | getMinJump([1, 2, 3, 5]) // -> 4 42 | getMinJump([3, 7, 5]) // -> 2 43 | getMinJump([9, 5, 1]) // -> 2 44 | */ 45 | ``` 46 | 47 | La dificultad del reto está en pensar que sólo podemos configurar el salto del trineo una vez y que buscamos el salto mínimo que nos serviría para sortear todos los obstaculos. -------------------------------------------------------------------------------- /22 - Cuantos adornos necesita el árbol/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | ¡Ay! Que llega la Navidad y no hemos decorado todavía el árbol. 🎄😱 4 | 5 | Necesitamos una función que pasándole un árbol binario nos diga el número de decoraciones que necesitamos. Para ello tenemos un objeto que sería la representación del árbol y que nos indica en cada nivel el número de ramas a decorar. 6 | 7 | Lo mejor es que veamos un ejemplo: 8 | 9 | ```javascript 10 | // tenemos el árbol en forma de objeto 11 | const tree = { 12 | value: 1, // el nodo raíz siempre es uno, porque es la estrella ⭐ 13 | left: { 14 | value: 2, // el nodo izquierdo necesita dos decoraciones 15 | left: null, // no tiene más ramas 16 | right: null // no tiene más ramas 17 | }, 18 | right: { 19 | value: 3, // el nodo de la derecha necesita tres decoraciones 20 | left: null, // no tiene más ramas 21 | right: null // no tiene más ramas 22 | } 23 | } 24 | 25 | /* Gráficamente sería así: 26 | 1 27 | / \ 28 | 2 3 29 | 30 | 1 + 2 + 3 = 5 31 | */ 32 | 33 | countDecorations(tree) // 5 34 | 35 | const bigTree = { 36 | value: 1, 37 | left: { 38 | value: 5, 39 | left: { 40 | value: 7, 41 | left: { 42 | value: 3, 43 | left: null, 44 | right: null 45 | }, 46 | right: null 47 | }, 48 | right: null 49 | }, 50 | right: { 51 | value: 6, 52 | left: { 53 | value: 5, 54 | left: null, 55 | right: null 56 | }, 57 | right: { 58 | value: 1, 59 | left: null, 60 | right: null 61 | } 62 | } 63 | } 64 | 65 | /* 66 | 1 67 | / \ 68 | 5 6 69 | / / \ 70 | 7 5 1 71 | / 72 | 3 73 | */ 74 | 75 | countDecorations(bigTree) // 28 76 | ``` 77 | 78 | Por cierto, Bellf Gates me ha contado que este tipo de ejercicio es muy típico en las entrevistas de trabajo para programadores. ¿Lo sabías? -------------------------------------------------------------------------------- /19 - Qué deberíamos aprender en Platzi/index.js: -------------------------------------------------------------------------------- 1 | function learn(time, courses) { 2 | var bestTime = 0 3 | var bestCourses = courses.reduce((acc, course, i) => { 4 | const possibleCourses = [...courses].splice(i + 1).filter(possibleCourse => (possibleCourse + course) <= time) 5 | if (possibleCourses.length){ 6 | const possibleCourse = Math.max(...possibleCourses) 7 | if ((possibleCourse + course) > bestTime) { 8 | bestTime = possibleCourse + course 9 | acc = [i, courses.indexOf(possibleCourse)] 10 | } 11 | } 12 | return acc; 13 | }, []); 14 | return bestCourses.length ? bestCourses : null 15 | } 16 | 17 | function learnFor(time, courses) { 18 | var bestTime = 0; 19 | var arr = null; 20 | for(let i = 0 ; i < courses.length ; i++) { 21 | for (let j = i + 1; j < courses.length; j++) { 22 | if (i === j) continue; 23 | const sum = courses[i] + courses[j]; 24 | 25 | if(sum > bestTime && sum <= time) { 26 | bestTime = sum; 27 | arr = [i, j]; 28 | } 29 | } 30 | } 31 | return arr 32 | } 33 | 34 | 35 | console.log(learnFor(10, [2, 3, 8, 1, 4])) // [0, 2] -> con 10 horas disponibles lo mejor es que completemos los cursos en el índice 0 y 2. 36 | console.log(learnFor(15, [2, 10, 4, 1])) // [1, 2] -> Los cursos en [1, 2] son 14 horas, es la mejor opción. 37 | console.log(learnFor(25, [10, 15, 20, 5])) // [0, 1] -> los cursos [0, 1] y [2, 3] completan exactamente con 25 horas pero siempre devolvemos el primero que encontremos 38 | console.log(learnFor(8, [8, 2, 1])) // [1, 2] -> para hacer dos cursos, no podemos hacer el de 8 horas, así que devolvemos el de 1 y 2. 39 | console.log(learnFor(8, [8, 2, 1, 4, 3])) // [3, 4] -> usamos el máximo tiempo disponible así que [3, 4] usa 7 horas y el [1, 2] sólo usaría 3 horas. 40 | console.log(learnFor(4, [10, 14, 20])) // null -> no nos da tiempo a hacer dos cursos 41 | console.log(learnFor(5, [5, 5, 5])) // null -> no nos da tiempo a hacer dos cursos -------------------------------------------------------------------------------- /17 - La locura de enviar paquetes en esta época/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Las empresas de paquetería 📦 se preparan para la época de fiestas y la locura de envíos que les espera. 4 | 5 | La empresa funciona con flotas de furgonetas 🚛 y camiones 🚚. Las flotas tienen un organigrama, ya que existen rangos de nivel de experiencia. 6 | 7 | Necesitamos saber el número de paquetes que una persona va a poder gestionar en un día. Para ello se cuenta el número de paquetes que puede llevar esa persona y **todos los transportistas que tiene en su equipo**. Lo malo es que los datos están almacenados de una forma un poco rara en un array: 8 | 9 | - El array contiene otros arrays que contienen los datos de cada transportista 10 | - `transportista[0]` -> Nombre/ID del Transportista 11 | - `transportista[1]` -> Paquetes que gestiona en un día 12 | - `transportista[2]` -> Array con sus subordinados 13 | 14 | Para que lo veamos en código, tanto el array, como la función de dos parámetros para conseguir el número deseado: 15 | 16 | ```javascript 17 | const carriers = [ 18 | ['dapelu', 5, ['midu', 'jelowing']], 19 | ['midu', 2, []], 20 | ['jelowing', 2, []] 21 | ] 22 | 23 | countPackages(carriers, 'dapelu') // 9 24 | // 5 de dapelu, 2 de midu y 2 de jelowing = 9 25 | 26 | const carriers2 = [ 27 | ['lolivier', 8, ['camila', 'jesuspoleo']], 28 | ['camila', 5, ['sergiomartinez', 'conchaasensio']], 29 | ['jesuspoleo', 4, []], 30 | ['sergiomartinez', 4, []], 31 | ['conchaasensio', 3, ['facundocapua', 'faviola']], 32 | ['facundocapua', 2, []], 33 | ['faviola', 1, []] 34 | ] 35 | 36 | countPackages(2, 'camila') // 15 37 | // 5 de camila, 4 de sergiomartinez, 3 de conchaasensio, 2 de facundocapua y 1 de faviola = 15 38 | ``` 39 | 40 | **¡Ten cuidado!** Como has visto en el segundo ejemplo, **el organigrama puede tener diferentes niveles y además nos viene información que puede ser que no necesitemos**. Debemos tener en cuenta el parámetro de `carrierID` para calcular bien el número y contar todo su equipo. -------------------------------------------------------------------------------- /21 - La ruta con los regalos/index.js: -------------------------------------------------------------------------------- 1 | function canCarry(capacity, trip) { 2 | const paradaMax = Math.max(... trip.reduce((acc, parada) => [...acc, parada[2]])) 3 | const paradas = Array.from({length: paradaMax}, (_, i) => i + 1) 4 | return paradas.reduce((regalosEncima, numParada) => { 5 | const parada = trip.filter(parada => parada[1] === numParada)[0] || null 6 | const paradasDejarRegalos = trip.filter(tmpParada => tmpParada[2] === numParada) 7 | const dejarRegalos = paradasDejarRegalos.reduce((acc, paradaDejarRegalo) => acc + paradaDejarRegalo[0], 0) || 0 8 | const cogerRegalos = parada ? parada[0] : 0 9 | regalosEncima = regalosEncima + cogerRegalos - dejarRegalos 10 | if (regalosEncima > capacity) { 11 | return false 12 | } 13 | return regalosEncima 14 | }, 0) === 0 ? true : false 15 | } 16 | 17 | 18 | 19 | 20 | 21 | console.log(canCarry(4, [[2, 5, 8], [3, 6, 10]])) // false 22 | // En el punto 5 recoge 2 regalos... 23 | // En el punto 6 recoge 3 regalos... 24 | // Del punto 6 al 8 tendría 5 regalos en total 25 | // Y su capacidad es 4... así que ¡no podría! 26 | 27 | console.log(canCarry(3, [[1, 1, 5], [2, 2, 10]])) // true 28 | // En el punto 1 recoge 1 regalo... 29 | // En el punto 2 recoge 2 regalos... 30 | // En el punto 5 entrega 1 regalo... 31 | // En el punto 10 entrega 2 regalos... 32 | // ¡Sí puede! Nunca superó la carga máxima de 3 regalos 33 | 34 | console.log(canCarry(3, [[2, 1, 5],[3, 5, 7]])) // true -> nunca supera el máximo de capacidad 35 | console.log(canCarry(4, [[2, 3, 8],[2, 5, 7]])) // true -> del punto 5 al 7 lleva 4 regalos y no supera el máximo 36 | 37 | console.log(canCarry(1, [[2, 3, 8]])) // false -> no podría ni con el primer viaje 38 | console.log(canCarry(2, [[1, 2, 4], [2, 3, 8]])) // false -> del punto 3 al 4 supera la capacidad máxima porque llevaría 3 regalos 39 | console.log(canCarry(11, [[3, 2, 7], [3, 7, 9], [8, 3, 9]])); // true 40 | console.log(canCarry(5, [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8]])); // false -------------------------------------------------------------------------------- /21 - La ruta con los regalos/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Se están preparando las rutas para el trineo de Santa 🎅. Tenemos almacenes por todo el mundo para que Santa pueda recoger los regalos y entregarlos en el destino final. 🎁 4 | 5 | Necesitamos saber si las rutas que estamos creando tienen sentido o si Santa va a tener que dejar tirados regalos por el camino. 🥺 6 | 7 | Para eso vamos a crear una función que recibe dos parámetros: 8 | 9 | - Un número con la **capacidad máxima de regalos en el trineo**. 10 | - El viaje que es un array de arrays. Cada subarray contiene tres números que representan: 11 | - `trip[0]` = número de regalos a transportar 12 | - `trip[1]` = punto de recogida de los regalos 13 | - `trip[2]` = punto de entrega de los regalos 14 | La ruta siempre va de izquierda a derecha (nunca volverá Santa hacia atrás) pero... ¡ten en cuenta que en mitad de la ruta puede tener que recoger regalos cuando ya tiene alguno encima! 15 | 16 | Lo mejor es que veamos un ejemplo: 17 | 18 | ```javascript 19 | canCarry(4, [[2, 5, 8], [3, 6, 10]]) // false 20 | // En el punto 5 recoge 2 regalos... 21 | // En el punto 6 recoge 3 regalos... 22 | // Del punto 6 al 8 tendría 5 regalos en total 23 | // Y su capacidad es 4... así que ¡no podría! 24 | 25 | canCarry(3, [[1, 1, 5], [2, 2, 10]]) // true 26 | // En el punto 1 recoge 1 regalo... 27 | // En el punto 2 recoge 2 regalos... 28 | // En el punto 5 entrega 1 regalo... 29 | // En el punto 10 entrega 2 regalos... 30 | // ¡Sí puede! Nunca superó la carga máxima de 3 regalos 31 | 32 | canCarry(3, [[2, 1, 5],[3, 5, 7]]) // true -> nunca supera el máximo de capacidad 33 | canCarry(4, [[2, 3, 8],[2, 5, 7]]) // true -> del punto 5 al 7 lleva 4 regalos y no supera el máximo 34 | 35 | canCarry(1, [[2, 3, 8]]) // false -> no podría ni con el primer viaje 36 | canCarry(2, [[1, 2, 4], [2, 3, 8]]) // false -> del punto 3 al 4 supera la capacidad máxima porque llevaría 3 regalos 37 | ``` 38 | 39 | Lo difícil, e importante, es que entiendas que Santa Claus **va entregando y recogiendo regalos y que a veces eso puede hacer que supere la carga máxima**. -------------------------------------------------------------------------------- /19 - Qué deberíamos aprender en Platzi/README.md: -------------------------------------------------------------------------------- 1 | ### Descripción del reto 2 | 3 | Con motivo de las fechas más bonitas del año, en [Platzi han lanzado una promoción muy especial](https://platzi.com/navidad/?utm_source=partnerships&utm_medium=paid&utm_campaign=MX_web_MiguelA_UF&utm_content=post) porque **la educación es un regalo 🎁 para siempre**. 4 | 5 | En Platzi tienen **más de 800 cursos** 📚 pero, claro, nuestro tiempo es limitado. Así que vamos a optimizar nuestro tiempo disponible para **completar dos cursos usando el máximo número de horas disponible**. 6 | 7 | Tenemos que crear **una función que recibe dos parámetros**. El primero es el número de horas que tenemos disponible ⏳ y el segundo es un array donde cada índice es un curso y el valor el tiempo que se tarda en completar. 8 | 9 | **Tenemos claro que queremos hacer dos cursos** así que la función debe devolver un array con el índice de los dos cursos que vamos a poder completar con el tiempo disponible proporcionado y **usando el máximo tiempo disponible**. Si no nos da tiempo, devolvemos `null` 10 | 11 | Vamos a ver unos ejemplos: 12 | 13 | 14 | ```javascript 15 | learn(10, [2, 3, 8, 1, 4]) // [0, 2] -> con 10 horas disponibles lo mejor es que completemos los cursos en el índice 0 y 2. 16 | 17 | learn(15, [2, 10, 4, 1]) // [1, 2] -> Los cursos en [1, 2] son 14 horas, es la mejor opción. 18 | 19 | learn(25, [10, 15, 20, 5]) // [0, 1] -> los cursos [0, 1] y [2, 3] completan exactamente con 25 horas pero siempre devolvemos el primero que encontremos 20 | 21 | learn(8, [8, 2, 1]) // [1, 2] -> para hacer dos cursos, no podemos hacer el de 8 horas, así que devolvemos el de 1 y 2. 22 | 23 | learn(8, [8, 2, 1, 4, 3]) // [3, 4] -> usamos el máximo tiempo disponible así que [3, 4] usa 7 horas y el [1, 2] sólo usaría 3 horas. 24 | 25 | learn(4, [10, 14, 20]) // null -> no nos da tiempo a hacer dos cursos 26 | 27 | learn(5, [5, 5, 5]) // null -> no nos da tiempo a hacer dos cursos 28 | ``` 29 | 30 | Mirando todo el tema de Platzi, además nos hemos dado cuenta que tienen [un descuento especial para Navidad](https://platzi.com/navidad/?utm_source=partnerships&utm_medium=paid&utm_campaign=MX_web_MiguelA_UF&utm_content=post). ¿No sabes qué regalar? **Regala conocimiento** 🎓. -------------------------------------------------------------------------------- /10 - La máquina de cambio/index.js: -------------------------------------------------------------------------------- 1 | const coins = [1, 2, 5, 10, 20, 50] 2 | // Solución con bucle for 3 | function getCoins(change) { 4 | var cambio = Array(coins.length).fill(0) 5 | for (let i = coins.length-1; i >= 0; i--) { 6 | if(change / coins[i] >= 1){ 7 | cambio[i] = Math.floor(change / coins[i]) 8 | change = change % coins[i] 9 | } 10 | } 11 | return cambio 12 | } 13 | 14 | // Solución con .map() 15 | function getCoins2(change){ 16 | return [...coins].reverse().map( coin => { 17 | let neededCoins = Math.floor(change / coin) 18 | change = change % coin 19 | return neededCoins 20 | }).reverse() 21 | } 22 | 23 | // Solución con .reduce() 24 | function getCoins3(change){ 25 | return [...coins].reverse().reduce( (acc, coin, i) => { 26 | acc[i] = Math.floor(change / coin) 27 | change = change % coin 28 | return acc; 29 | }, Array(coins.length).fill(0)).reverse() 30 | } 31 | 32 | 33 | console.log(getCoins(51)); // [1, 0, 0, 0, 0, 1] -> una moneda de 1 céntimo y otra de 50 céntimos 34 | console.log(getCoins2(51)); // [1, 0, 0, 0, 0, 1] -> una moneda de 1 céntimo y otra de 50 céntimos 35 | console.log(getCoins3(51)); // [1, 0, 0, 0, 0, 1] -> una moneda de 1 céntimo y otra de 50 céntimos 36 | 37 | console.log(getCoins(3)); // [1, 1, 0, 0, 0, 0] -> una moneda de 1 céntimo y otra de 2 38 | console.log(getCoins2(3)); // [1, 1, 0, 0, 0, 0] -> una moneda de 1 céntimo y otra de 2 39 | console.log(getCoins3(3)); // [1, 1, 0, 0, 0, 0] -> una moneda de 1 céntimo y otra de 2 40 | 41 | console.log(getCoins(5)); // [0, 0, 1, 0, 0, 0] -> una moneda de 5 céntimos 42 | console.log(getCoins2(5)); // [0, 0, 1, 0, 0, 0] -> una moneda de 5 céntimos 43 | console.log(getCoins3(5)); // [0, 0, 1, 0, 0, 0] -> una moneda de 5 céntimos 44 | 45 | console.log(getCoins(16)); // [1, 0, 1, 1, 0, 0] -> una moneda de 1 céntimo, una de 5 y una de 10 46 | console.log(getCoins2(16)); // [1, 0, 1, 1, 0, 0] -> una moneda de 1 céntimo, una de 5 y una de 10 47 | console.log(getCoins3(16)); // [1, 0, 1, 1, 0, 0] -> una moneda de 1 céntimo, una de 5 y una de 10 48 | 49 | console.log(getCoins(100)); // [0, 0, 0, 0, 0, 2] -> dos monedas de 50 céntimos 50 | console.log(getCoins2(100)); // [0, 0, 0, 0, 0, 2] -> dos monedas de 50 céntimos 51 | console.log(getCoins3(100)); // [0, 0, 0, 0, 0, 2] -> dos monedas de 50 céntimos --------------------------------------------------------------------------------