diff --git a/.gitignore b/.gitignore index 7e6a3b796..53e6c00ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ - +.vscode # Created by https://www.toptal.com/developers/gitignore/api/android,androidstudio,kotlin # Edit at https://www.toptal.com/developers/gitignore?templates=android,androidstudio,kotlin diff --git a/soluciones-javascript/01-fizzbuzz/app.js b/soluciones-javascript/01-fizzbuzz/app.js new file mode 100644 index 000000000..98dabb19c --- /dev/null +++ b/soluciones-javascript/01-fizzbuzz/app.js @@ -0,0 +1,29 @@ +/* + *#1 EL FAMOSO "FIZZ BUZZ"* + *** + * Escribe un programa que muestre por consola (con un print) los + * números de 1 a 100 (ambos incluidos y con un salto de línea entre + * cada impresión), sustituyendo los siguientes: + * - Múltiplos de 3 por la palabra "fizz". + * - Múltiplos de 5 por la palabra "buzz". + * - Múltiplos de 3 y de 5 a la vez por la palabra "fizzbuzz". + */ +const fizzBuzz = () => { + + for (let i = 1; i <= 100; i++) { + + if(i % 3 === 0 && i % 5 === 0){ + console.log("fizzbuzz"); + }else if (i % 3 === 0) { + console.log("fizz"); + }else if( i % 5 === 0){ + console.log("buzz"); + }else{ + console.log(i); + } + + } + +} + +fizzBuzz(); \ No newline at end of file diff --git a/soluciones-javascript/02-anagrama/app.js b/soluciones-javascript/02-anagrama/app.js new file mode 100644 index 000000000..5fe643f09 --- /dev/null +++ b/soluciones-javascript/02-anagrama/app.js @@ -0,0 +1,40 @@ +/* + * Escribe una función que reciba dos palabras (String) y retorne + * verdadero o falso (Bool) según sean o no anagramas. + * - Un Anagrama consiste en formar una palabra reordenando TODAS + * las letras de otra palabra inicial. + * - NO hace falta comprobar que ambas palabras existan. + * - Dos palabras exactamente iguales no son anagrama. + */ + +const isAnagram = (string1 = '', string2 = '') => { + + //Si algún String está vacío retorna false + if(!string1 || !string2 ) return false; + + if(string1.length !== string2.length ) return false; + + const stringLowerCase1 = string1.toLowerCase().trim(); + const stringLowerCase2 = string2.toLowerCase().trim(); + + //Si las palabras son exactamente iguales retorna false + if(stringLowerCase1 === stringLowerCase2) return false; + + const arrayString1 = stringLowerCase1.split("").sort().join(''); + const arrayString2 = stringLowerCase2.split("").sort().join(''); + + return arrayString1 === arrayString2; + +} + + +console.log("Es un anagrama (amor + roma): " + isAnagram("amor", "roma")); +console.log("Es un anagrama (listen + silent): " + isAnagram("listen", "silent")); +console.log("Es un anagrama (test + test): " + isAnagram("test", "test")); +console.log("Es un anagrama ( + word): " + isAnagram("", "word")); +console.log("Es un anagrama (test + testing): " + isAnagram("test", "testing")); +console.log("Es un anagrama (Listen + Silent): " + isAnagram("Listen", "Silent")); +console.log("Es un anagrama (Dormitory + Dirty room): " + isAnagram("Dormitory", "Dirty room")); + + + diff --git a/soluciones-javascript/03-fibonacci/app.js b/soluciones-javascript/03-fibonacci/app.js new file mode 100644 index 000000000..6777a9940 --- /dev/null +++ b/soluciones-javascript/03-fibonacci/app.js @@ -0,0 +1,33 @@ +/* + * * LA SUCESIÓN DE FIBONACCI * + * Escribe un programa que imprima los 50 primeros números de la sucesión + * de Fibonacci empezando en 0. + * - La serie Fibonacci se compone por una sucesión de números en + * la que el siguiente siempre es la suma de los dos anteriores. + * 0, 1, 1, 2, 3, 5, 8, 13... + */ + + +const sucesionFibonacci = ( cantidadNumeros ) => { + + if ( cantidadNumeros < 0 ) return console.log(0); + + let anterior = 0; + let actual = 1; + + for (let i = 0; i < cantidadNumeros; i++) { + + console.log(`${ i + 1 }_: ${anterior}`); + + let temp = anterior; + anterior = actual + anterior; + actual = temp; + + } + + +} + + + +sucesionFibonacci( 50 ); diff --git a/soluciones-javascript/04-numero-primo/app.js b/soluciones-javascript/04-numero-primo/app.js new file mode 100644 index 000000000..0d230afa6 --- /dev/null +++ b/soluciones-javascript/04-numero-primo/app.js @@ -0,0 +1,24 @@ +/* + * Escribe un programa que se encargue de comprobar si un número es o no primo. + * Hecho esto, imprime los números primos entre 1 y 100. + */ + +const esNumeroPrimo = (numero) => { + if (numero <= 1) return false; + + if (numero === 2) return true; + + for (let i = 2; i <= Math.sqrt(numero); i++) { + if (numero % i === 0) { + return false; + } + } + + return true; +}; + +for (let i = 2; i < 100; i++) { + if (esNumeroPrimo(i)) { + console.log(i); + } +} diff --git a/soluciones-javascript/05-area-poligono/app.js b/soluciones-javascript/05-area-poligono/app.js new file mode 100644 index 000000000..0fdb4d323 --- /dev/null +++ b/soluciones-javascript/05-area-poligono/app.js @@ -0,0 +1,41 @@ +/* + * Crea una única función (importante que sólo sea una) que sea capaz + * de calcular y retornar el área de un polígono. + * - La función recibirá por parámetro sólo UN polígono a la vez. + * - Los polígonos soportados serán Triángulo, Cuadrado y Rectángulo. + * - Imprime el cálculo del área de un polígono de cada tipo. + */ + +const areaPoligono = ({ tipo = "", datosPoligono = {} }) => { + + const esPositivo = (n) => typeof n === 'number' && n > 0; + + switch (tipo) { + case "Triangulo": + if ( esPositivo(datosPoligono.base) && esPositivo(datosPoligono.altura) ) { + return (datosPoligono.base * datosPoligono.altura) / 2; + }else{ + throw new Error("Los datos del triangulo deben ser positivos"); + } + case "Cuadrado": + if ( esPositivo(datosPoligono.lado) ) { + return datosPoligono.lado * datosPoligono.lado; + }else{ + throw new Error("Los datos del Cuadrado deben ser positivos"); + } + case "Rectangulo": + if ( esPositivo(datosPoligono.base) && esPositivo(datosPoligono.altura) ) { + return datosPoligono.base * datosPoligono.altura; + }else{ + throw new Error("Los datos del Rectangulo deben ser positivos"); + } + default: + throw new Error("Especifica un dato correcto"); + } + +} + +// Ejemplos de uso +console.log(areaPoligono({ tipo: "Triangulo", datosPoligono: { base: 2, altura: 4 } })); +console.log(areaPoligono({ tipo: "Cuadrado", datosPoligono: { lado: 5 } })); +console.log(areaPoligono({ tipo: "Rectangulo", datosPoligono: { base: 3, altura: 6 } })); \ No newline at end of file diff --git a/soluciones-javascript/06-aspect-ratio-image/app.js b/soluciones-javascript/06-aspect-ratio-image/app.js new file mode 100644 index 000000000..fce15cbc0 --- /dev/null +++ b/soluciones-javascript/06-aspect-ratio-image/app.js @@ -0,0 +1,43 @@ +/* + * Crea un programa que se encargue de calcular el aspect ratio de una + * imagen a partir de una url. + * - Url de ejemplo: + * https://es.vitejs.dev/og-image-announcing-vite3.png + * - Por ratio hacemos referencia por ejemplo a los "16:9" de una + * imagen de 1920*1080px. + */ + + +const calcularAspectRatio = async (url) => { + + const img = new Image(); + + img.src = url; + + img.onload = () => { + const width = img.width; + const height = img.height; + + // Maximo comun divisor + const mcd = ( a, b ) => b === 0 ? a : mcd( b, a % b ); + + console.log(mcd(width, height)); + + const ratioMCD = mcd(width, height); + + console.log(`La resolución de la imagen es ${width}x${height}`); + console.log(`La relación de aspecto es: ${ width / ratioMCD }:${ height / ratioMCD }`); + + + } + + img.onerror = () => { + console.error('No se pudo cargar la imagen'); + } + + return img; + +} + +const url = "https://cdn.unotv.com/images/2024/03/mazapan-perrito-influencer-143900-1024x576.jpeg" +calcularAspectRatio(url); \ No newline at end of file diff --git a/soluciones-javascript/06-aspect-ratio-image/index.html b/soluciones-javascript/06-aspect-ratio-image/index.html new file mode 100644 index 000000000..916bfeafc --- /dev/null +++ b/soluciones-javascript/06-aspect-ratio-image/index.html @@ -0,0 +1,11 @@ + + + + + + Ejercicio de programación + + + + + \ No newline at end of file diff --git a/soluciones-javascript/07-inviertiendo-cadenas/app.js b/soluciones-javascript/07-inviertiendo-cadenas/app.js new file mode 100644 index 000000000..8ece70480 --- /dev/null +++ b/soluciones-javascript/07-inviertiendo-cadenas/app.js @@ -0,0 +1,22 @@ +/* + * Crea un programa que invierta el orden de una cadena de texto + * sin usar funciones propias del lenguaje que lo hagan de forma automática. + * - Si le pasamos "Hola mundo" nos retornaría "odnum aloH" + */ + +const reverseTextString = (string) => { + + const stringFormatter = string.trim(); + let reverseText = ""; + + for (let i = 1; i <= stringFormatter.length; i++) { + + reverseText += stringFormatter[ stringFormatter.length - i]; + + } + + return reverseText; + +} + +console.log(reverseTextString(" Hola Mundo ")); \ No newline at end of file diff --git a/soluciones-javascript/07-inviertiendo-cadenas/index.html b/soluciones-javascript/07-inviertiendo-cadenas/index.html new file mode 100644 index 000000000..5a798babe --- /dev/null +++ b/soluciones-javascript/07-inviertiendo-cadenas/index.html @@ -0,0 +1,11 @@ + + + + + + Invirtiendo cadenas + + + + + \ No newline at end of file diff --git a/soluciones-javascript/08-contando-palabras/app.js b/soluciones-javascript/08-contando-palabras/app.js new file mode 100644 index 000000000..1bfbb36d1 --- /dev/null +++ b/soluciones-javascript/08-contando-palabras/app.js @@ -0,0 +1,25 @@ +/* + * Crea un programa que cuente cuantas veces se repite cada palabra + * y que muestre el recuento final de todas ellas. + * - Los signos de puntuación no forman parte de la palabra. + * - Una palabra es la misma aunque aparezca en mayúsculas y minúsculas. + * - No se pueden utilizar funciones propias del lenguaje que + * lo resuelvan automáticamente. + */ + +const countWords = (text) => { + const cleanedText = text.toLowerCase().replace(/[^\w\s]/g, ''); + + const wordsArray = cleanedText.split(/\s+/).filter( word => word !== ''); + + const wordCount = {}; + console.log({cleanedText}, {wordsArray}); + + wordsArray.forEach(word => { + wordCount[word] = (wordCount[word] || 0) + 1; + }); + + console.log( { wordsArray, wordCount } ); +}; + +countWords(" Hola, asd una páasdlabra d asd asd repetida,, hotra a a dsad sad palabraasd repetida paasdq3wrlabra o hola "); diff --git a/soluciones-javascript/08-contando-palabras/index.html b/soluciones-javascript/08-contando-palabras/index.html new file mode 100644 index 000000000..7e9e5a84d --- /dev/null +++ b/soluciones-javascript/08-contando-palabras/index.html @@ -0,0 +1,12 @@ + + + + + + Contando Palabras + + +

Abre la consola y mira el resultado

+ + + \ No newline at end of file diff --git a/soluciones-javascript/09-decimal-binario/app.js b/soluciones-javascript/09-decimal-binario/app.js new file mode 100644 index 000000000..1d0d3c7a4 --- /dev/null +++ b/soluciones-javascript/09-decimal-binario/app.js @@ -0,0 +1,20 @@ +/* + * Crea un programa se encargue de transformar un número + * decimal a binario sin utilizar funciones propias del lenguaje que lo hagan directamente. + */ + +const decimalToBinary = (number) => { + let numberBinary = []; + let numberNew = number; + + while (numberNew > 0) { + numberBinary.unshift(Math.floor(numberNew % 2)); + numberNew = Math.floor(numberNew / 2); + } + + return numberBinary.join(""); + + +}; + +console.log(decimalToBinary(10)); diff --git a/soluciones-javascript/09-decimal-binario/index.html b/soluciones-javascript/09-decimal-binario/index.html new file mode 100644 index 000000000..6e7aece82 --- /dev/null +++ b/soluciones-javascript/09-decimal-binario/index.html @@ -0,0 +1,12 @@ + + + + + + 09 Decimal a Binario + + +

Abre la consola para ver el ejercicio

+ + + \ No newline at end of file diff --git a/soluciones-javascript/10-codigo-morse/app.js b/soluciones-javascript/10-codigo-morse/app.js new file mode 100644 index 000000000..55fc38d31 --- /dev/null +++ b/soluciones-javascript/10-codigo-morse/app.js @@ -0,0 +1,32 @@ +/* + * Crea un programa que sea capaz de transformar texto natural a código + * morse y viceversa. + * - Debe detectar automáticamente de qué tipo se trata y realizar + * la conversión. + * - En morse se soporta raya "—", punto ".", un espacio " " entre letras + * o símbolos y dos espacios entre palabras " ". + * - El alfabeto morse soportado será el mostrado en + * https://es.wikipedia.org/wiki/Código_morse. + */ + +console.log({dataMorseCode}); + +const codigoMorse = (text) => { + + return text.toUpperCase().split('').map( word => { + + if(dataMorseCode[word]){ + return dataMorseCode[word] + } else if (word === " "){ + return "/"; + }else { + return ""; + } + + }).join(" "); + +} + +console.log(codigoMorse("Prueba x")); +console.log(codigoMorse("Otra prueba con diferasduhwq signficado, ayuda ´++´{}")); +console.log(codigoMorse("Me gusta la cigueña, la malta y la inmal también jaja esxs xsxsada")); \ No newline at end of file diff --git a/soluciones-javascript/10-codigo-morse/dataMorseCode.js b/soluciones-javascript/10-codigo-morse/dataMorseCode.js new file mode 100644 index 000000000..63ed31223 --- /dev/null +++ b/soluciones-javascript/10-codigo-morse/dataMorseCode.js @@ -0,0 +1,11 @@ +const dataMorseCode = { + A: ".-", B: "-...", C: "-.-.", D: "-..", + E: ".", F: "..-.", G: "--.", H: "....", + I: "..", J: ".---", K: "-.-", L: ".-..", + M: "--", N: "-.", Ñ: "--.--", O: "---", + P: ".--.", Q: "--.-", R: ".-.", S: "...", + T: "-", U: "..-", V: "...-", W: ".--", + X: "-..-", Y: "-.--", Z: "--..", + '0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-', + '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.' +}; diff --git a/soluciones-javascript/10-codigo-morse/index.html b/soluciones-javascript/10-codigo-morse/index.html new file mode 100644 index 000000000..a0726581e --- /dev/null +++ b/soluciones-javascript/10-codigo-morse/index.html @@ -0,0 +1,13 @@ + + + + + + Codigo morse + + +

Abre la consola y mira el resultado

+ + + + \ No newline at end of file diff --git a/soluciones-javascript/11-expresiones-equilibradas/app.js b/soluciones-javascript/11-expresiones-equilibradas/app.js new file mode 100644 index 000000000..95aa88163 --- /dev/null +++ b/soluciones-javascript/11-expresiones-equilibradas/app.js @@ -0,0 +1,48 @@ +/* + * Crea un programa que comprueba si los paréntesis, llaves y corchetes + * de una expresión están equilibrados. + * - Equilibrado significa que estos delimitadores se abren y cieran + * en orden y de forma correcta. + * - Paréntesis, llaves y corchetes son igual de prioritarios. + * No hay uno más importante que otro. + * - Expresión balanceada: { [ a * ( c + d ) ] - 5 } + * - Expresión no balanceada: { a * ( c + d ) ] - 5 } + */ + +/** + * + * @param {String} expression + */ +const isBalanced = (expression) => { + const expressionWithoutSpace = expression.replace(/\s+/g, ""); + + let stackExpr = []; + + for (let i = 0; i < expressionWithoutSpace.length; i++) { + const char = expressionWithoutSpace[i]; + + if (char === "{" || char === "[" || char === "(") { + stackExpr.push(char); + } else if (char === "}" || char === "]" || char === ")") { + if (stackExpr.length === 0) { + return false; + } + + const last = stackExpr.pop(); + + if ( + (char === "}" && last !== "{") || + (char === "]" && last !== "[") || + (char === ")" && last !== "(") + ) { + return false; + } + } + } + + return stackExpr.length === 0; +}; + +console.log(isBalanced("{ [ a * ( c + d ) ] - 5 }")); +console.log(isBalanced("{ a * ( c + d ) ] - 5 }")); +console.log(isBalanced("{ [ ((a - b) + (-4 * a)) * ( c + d ) ] - 5 }")); diff --git a/soluciones-javascript/11-expresiones-equilibradas/index.html b/soluciones-javascript/11-expresiones-equilibradas/index.html new file mode 100644 index 000000000..e1ec91e64 --- /dev/null +++ b/soluciones-javascript/11-expresiones-equilibradas/index.html @@ -0,0 +1,12 @@ + + + + + + Expresiones Equilibradas + + +

Abre la consola y mira el resultado

+ + + \ No newline at end of file diff --git a/soluciones-javascript/12-eliminando-caracteres/app.js b/soluciones-javascript/12-eliminando-caracteres/app.js new file mode 100644 index 000000000..c30537792 --- /dev/null +++ b/soluciones-javascript/12-eliminando-caracteres/app.js @@ -0,0 +1,34 @@ +/* + * Crea una función que reciba dos cadenas como parámetro (str1, str2) + * e imprima otras dos cadenas como salida (out1, out2). + * - out1 contendrá todos los caracteres presentes en la str1 pero NO + * estén presentes en str2. + * - out2 contendrá todos los caracteres presentes en la str2 pero NO + * estén presentes en str1. + */ + +/** + * Función que recibe dos cadenas de texto como entrada y genera dos nuevas cadenas como salida + * - La primera cadena de salida (`out1`) contiene los caracteres presentes en `str1` pero no en `str2`. + * - La segunda cadena de salida (`out2`) contiene los caracteres presentes en `str2` pero no en `str1`. + * @param {String} str1 Cadena de texto 1 + * @param {String} str2 Cadena de texto 2 + * @returns {{ out1: string, out2: string }} Un objeto con dos propiedades: + * - `out1`: Cadena con los caracteres exclusivos de `str1`. + * - `out2`: Cadena con los caracteres exclusivos de `str2`. + */ +const eliminandoCaracteres = ( str1, str2 ) => { + + if( str1.trim() === str2.trim() ) return `Cadenas de texto iguales: Cadena 1: ${str1} Cadena 2: ${str2}`; + + const str1Unique = [...new Set(str1)]; + const str2Unique = [...new Set(str2)]; + + const out1 = str1Unique.filter( char => !str2Unique.includes(char)).join(''); + const out2 = str2Unique.filter( char => !str1Unique.includes(char)).join(''); + + return { out1, out2 } + +} + +console.log(eliminandoCaracteres('cadena similar', 'cadena diferente')); diff --git a/soluciones-javascript/12-eliminando-caracteres/index.html b/soluciones-javascript/12-eliminando-caracteres/index.html new file mode 100644 index 000000000..e2b120f24 --- /dev/null +++ b/soluciones-javascript/12-eliminando-caracteres/index.html @@ -0,0 +1,12 @@ + + + + + + Eliminando caracteres + + +

Abre la consola y observa la magia

+ + + \ No newline at end of file diff --git a/soluciones-javascript/13-palindromo/app.js b/soluciones-javascript/13-palindromo/app.js new file mode 100644 index 000000000..63e4b1566 --- /dev/null +++ b/soluciones-javascript/13-palindromo/app.js @@ -0,0 +1,32 @@ +/* + * #13 ¿Es un Palindromo? + * Escribe una función que reciba un texto y retorne verdadero o + * falso (Boolean) según sean o no palíndromos. + * Un Palíndromo es una palabra o expresión que es igual si se lee + * de izquierda a derecha que de derecha a izquierda. + * NO se tienen en cuenta los espacios, signos de puntuación y tildes. + * Ejemplo: Ana lleva al oso la avellana. + */ + +/** + * Función para verificar si una cadena de texto es palindromo o no + * @param {String} texto + */ +const esPalindromo = ( texto ) => { + + const textoFormateado = texto + .replace(/\s+/g, "") + .split('') + .map( (char, index, array) => array[ index === 0 ? array.length - 1 : array.length - (index + 1)] ) + .join('') + .toLowerCase(); + + return textoFormateado === texto.replace(/\s+/g, "").toLocaleLowerCase(); + + +} + +console.log(esPalindromo('Ana lleva al oso la avellana')); +console.log(esPalindromo('Sé verlas al revés')); +console.log(esPalindromo('Somos o no somos')); +console.log(esPalindromo('Ana lava lana')); \ No newline at end of file diff --git a/soluciones-javascript/13-palindromo/index.html b/soluciones-javascript/13-palindromo/index.html new file mode 100644 index 000000000..0a2f567a0 --- /dev/null +++ b/soluciones-javascript/13-palindromo/index.html @@ -0,0 +1,12 @@ + + + + + + Palindromo + + +

Abre La Consola y mira el resultado

+ + + \ No newline at end of file diff --git a/soluciones-javascript/14-factorial-recursivo/app.js b/soluciones-javascript/14-factorial-recursivo/app.js new file mode 100644 index 000000000..92034e851 --- /dev/null +++ b/soluciones-javascript/14-factorial-recursivo/app.js @@ -0,0 +1,15 @@ +/* + * Escribe una función que calcule y retorne el factorial de un número dado + * de forma recursiva. + */ + +const factorial = (n) => { + + if ( n <= 0 ) return 1; + + return n * factorial( n - 1 ); + +} + +console.log(factorial(3)); +console.log(factorial(10)); \ No newline at end of file diff --git a/soluciones-javascript/14-factorial-recursivo/index.html b/soluciones-javascript/14-factorial-recursivo/index.html new file mode 100644 index 000000000..e529b155e --- /dev/null +++ b/soluciones-javascript/14-factorial-recursivo/index.html @@ -0,0 +1,12 @@ + + + + + + Factorial recursivo + + +

Abre la consola y visualiza el resultado

+ + + \ No newline at end of file diff --git a/soluciones-javascript/15-numero-de-armstrong/app.js b/soluciones-javascript/15-numero-de-armstrong/app.js new file mode 100644 index 000000000..3f5c54899 --- /dev/null +++ b/soluciones-javascript/15-numero-de-armstrong/app.js @@ -0,0 +1,28 @@ +/* + * Escribe una función que calcule si un número dado es un número de Armstrong + * (o también llamado narcisista). + * Si no conoces qué es un número de Armstrong, debes buscar información + * al respecto. + */ + +/** + * Función para calcular si un número es un número de Armstrong o no. + * @param {Number} n : number + */ +const esNumeroArmstrong = (n) => { + if (n < 0) return false; + + const formattedNumber = n.toString().split("").map(Number); + const sumNumber = formattedNumber.reduce( + (prev, current) => prev + Math.pow(current, formattedNumber.length), + 0 + ); + + return sumNumber === n; +}; + +console.log(esNumeroArmstrong(153)); // true +console.log(esNumeroArmstrong(9474)); // true +console.log(esNumeroArmstrong(9475)); // false +console.log(esNumeroArmstrong(370)); // true + diff --git a/soluciones-javascript/15-numero-de-armstrong/index.html b/soluciones-javascript/15-numero-de-armstrong/index.html new file mode 100644 index 000000000..b6c9a859a --- /dev/null +++ b/soluciones-javascript/15-numero-de-armstrong/index.html @@ -0,0 +1,12 @@ + + + + + + Ejercicio 15 + + +

Ejercicio 15 - Abre la consola

+ + + \ No newline at end of file diff --git a/soluciones-javascript/16-cuantos-dias/app.js b/soluciones-javascript/16-cuantos-dias/app.js new file mode 100644 index 000000000..b9f1ece3b --- /dev/null +++ b/soluciones-javascript/16-cuantos-dias/app.js @@ -0,0 +1,37 @@ +/* + * Crea una función que calcule y retorne cuántos días hay entre dos cadenas + * de texto que representen fechas. + * - Una cadena de texto que representa una fecha tiene el formato "dd/MM/yyyy". + * - La función recibirá dos String y retornará un Int. + * - La diferencia en días será absoluta (no importa el orden de las fechas). + * - Si una de las dos cadenas de texto no representa una fecha correcta se + * lanzará una excepción. + */ + +/** + * + * @param {String} fecha1 : 'dd/mm/yyyy' + * @param {String} fecha2 : 'dd/mm/yyyy' + */ +const cuantosDias = (fecha1, fecha2) => { + const regexFecha = /^\d{2}\/\d{2}\/\d{4}$/; + if (!regexFecha.test(fecha1) || !regexFecha.test(fecha2)) + throw new Error("El formato de fechas es erróneo"); + + const fechaFormatted1 = new Date(fecha1).getTime(); + const fechaFormatted2 = new Date(fecha2).getTime(); + + const diferenciaDeDias = + fechaFormatted1 > fechaFormatted2 + ? fechaFormatted1 - fechaFormatted2 + : fechaFormatted2 - fechaFormatted1; + const diferenciaDeDiasFormateado = diferenciaDeDias / (1000 * 60 * 60 * 24); + + return diferenciaDeDiasFormateado; +}; + +console.log(cuantosDias("04/16/2006", "12/05/2006")); // Esperado: 233 +console.log(cuantosDias("12/05/2006", "04/16/2006")); // Esperado: 233 +console.log(cuantosDias("01/01/2023", "12/31/2023")); // Esperado: 364 +console.log(cuantosDias("01/01/2024", "01/01/2024")); // Esperado: 0 +console.log(cuantosDias("12/05/2006", "04162006")); diff --git a/soluciones-javascript/16-cuantos-dias/index.html b/soluciones-javascript/16-cuantos-dias/index.html new file mode 100644 index 000000000..045010469 --- /dev/null +++ b/soluciones-javascript/16-cuantos-dias/index.html @@ -0,0 +1,12 @@ + + + + + + Cuantos días + + +

Ejercicio 16 - Abre la consola y visualiza el resultado

+ + + \ No newline at end of file diff --git a/soluciones-javascript/17-en-mayuscula/app.js b/soluciones-javascript/17-en-mayuscula/app.js new file mode 100644 index 000000000..d21572a66 --- /dev/null +++ b/soluciones-javascript/17-en-mayuscula/app.js @@ -0,0 +1,22 @@ +/* + * Crea una función que reciba un String de cualquier tipo y se encargue de + * poner en mayúscula la primera letra de cada palabra. + * - No se pueden utilizar operaciones del lenguaje que + * lo resuelvan directamente. + */ + +/** + * + * @param {String} string + * @returns + */ +const inUpperCase = (string) => { + return string.split(' ').map(word => { + const firstLetterCap = word.charAt(0).toUpperCase(); + const remainingLetters = word.slice(1); + return firstLetterCap + remainingLetters; + }).join(' ').trim(); +} + +console.log(inUpperCase('debi tirar mas algo')); +console.log(inUpperCase(" hola mundo! esto es una prueba ")); diff --git a/soluciones-javascript/17-en-mayuscula/index.html b/soluciones-javascript/17-en-mayuscula/index.html new file mode 100644 index 000000000..339870fcf --- /dev/null +++ b/soluciones-javascript/17-en-mayuscula/index.html @@ -0,0 +1,11 @@ + + + + + + En Mayuscula + + + + + \ No newline at end of file diff --git a/soluciones-javascript/18-carrera-de-obstaculos/app.js b/soluciones-javascript/18-carrera-de-obstaculos/app.js new file mode 100644 index 000000000..44b9fc5b4 --- /dev/null +++ b/soluciones-javascript/18-carrera-de-obstaculos/app.js @@ -0,0 +1,61 @@ +/* + * Crea una función que evalúe si un/a atleta ha superado correctamente una + * carrera de obstáculos. + * - La función recibirá dos parámetros: + * - Un array que sólo puede contener String con las palabras + * "run" o "jump" + * - Un String que represente la pista y sólo puede contener "_" (suelo) + * o "|" (valla) + * - La función imprimirá cómo ha finalizado la carrera: + * - Si el/a atleta hace "run" en "_" (suelo) y "jump" en "|" (valla) + * será correcto y no variará el símbolo de esa parte de la pista. + * - Si hace "jump" en "_" (suelo), se variará la pista por "x". + * - Si hace "run" en "|" (valla), se variará la pista por "/". + * - La función retornará un Boolean que indique si ha superado la carrera. + * Para ello tiene que realizar la opción correcta en cada tramo de la pista. + */ + +/** + * Función para determinar si un atleta ha superado correctamente un carrera de obstaculos + * @param {Array} acciones Array de palabras run | jump + * @param {String} pista String que contiene la pista + */ +const carreraObstaculos = ( acciones, pista ) => { + + if ( acciones.length !== pista.length ) + throw new Error("Las longitudes no coinciden"); + + if( !Array.isArray(acciones) || typeof pista !== 'string') + throw new Error("Parámetros inválidos: Se espera un array y un string"); + + let resultado = true; + let nuevaPista = ''; + + acciones.forEach(( accion, index) => { + + const tramo = pista[index]; + + if( tramo === '_' && accion === 'run' ){ + nuevaPista += tramo; + } else if ( tramo === '|' && accion === 'jump' ){ + nuevaPista += tramo; + }else if( tramo === '_' && accion === 'jump' ){ + nuevaPista += 'x'; + resultado = false; + } else if ( pista[index] === '|' && accion === 'run' ){ + nuevaPista += '/'; + resultado = false; + } else { + throw new Error("Tramo no identificado"); + } + }); + + console.log(nuevaPista); + + return resultado; + +} + +const arrayDeAcciones = ['run', 'run', 'run', 'jump', 'run', 'jump', 'jump', 'jump', 'run', 'run', 'jump', 'run',]; + +carreraObstaculos( arrayDeAcciones, '___|_|||__|_'); \ No newline at end of file diff --git a/soluciones-javascript/18-carrera-de-obstaculos/index.html b/soluciones-javascript/18-carrera-de-obstaculos/index.html new file mode 100644 index 000000000..b113331e2 --- /dev/null +++ b/soluciones-javascript/18-carrera-de-obstaculos/index.html @@ -0,0 +1,12 @@ + + + + + + Carrera de ]Obstaculos + + +

ABRE LA CONSOLA

+ + + \ No newline at end of file diff --git a/soluciones-javascript/19-tres-en-raya/app.js b/soluciones-javascript/19-tres-en-raya/app.js new file mode 100644 index 000000000..5d82f7914 --- /dev/null +++ b/soluciones-javascript/19-tres-en-raya/app.js @@ -0,0 +1,97 @@ +/* + * Crea una función que analice una matriz 3x3 compuesta por "X" y "O" + * y retorne lo siguiente: + * - "X" si han ganado las "X" + * - "O" si han ganado los "O" + * - "Empate" si ha habido un empate + * - "Nulo" si la proporción de "X", de "O", o de la matriz no es correcta. + * O si han ganado los 2. + * Nota: La matriz puede no estar totalmente cubierta. + * Se podría representar con un vacío "", por ejemplo. + */ + +/** + * Función de Tres En Raya + * @param {Array} matriz del juego por el usuario + */ +const tresEnRaya = (matriz) => { + + if ((matriz[0].length !== 3) || (matriz[1].length !== 3) || (matriz[2].length !== 3)) + return "Nulo"; + + const arrayDeResultado = [ ...matriz[0], ...matriz[1], ...matriz[2] ]; + + const combinacionesGanadoras = [ + [0, 1, 2], + [3, 4, 5], + [6, 7, 8], + [0, 3, 6], + [1, 4, 7], + [2, 5, 8], + [0, 4, 8], + [2, 4, 6], + ]; + + const resultado = []; + + combinacionesGanadoras.forEach((combinacion) => { + const [ a, b, c ] = combinacion; + + if( + arrayDeResultado[a] !== " " && + arrayDeResultado[a] === arrayDeResultado[b] && + arrayDeResultado[a] === arrayDeResultado[c] + ){ + resultado.push(arrayDeResultado[a]); + } + + }); + + if ( resultado.includes('x') && resultado.includes('o')){ + return 'Nulo'; + } + + if (resultado.length === 0) { + return 'Empate'; + } + + if(resultado.length > 0){ + return resultado[0].toUpperCase(); + } + + return 'Nulo'; + +}; + +console.log( + "Gana O: " + + tresEnRaya([ + ["x", "x", "o"], + ["x", "o", " "], + ["o", " ", " "], + ]) +); +console.log( + "Gana x: " + + tresEnRaya([ + ["x", "x", "x"], + ["x", "o", "o"], + ["o", "o", "x"], + ]) +); + +console.log( + tresEnRaya([ + ["o", "o", "x"], + ["x", "x", "o"], + ["o", "o", "x"], + ]) +); + +console.log( + tresEnRaya([ + ["o", "o", "o"], + ["x", "x", "x"], + [" ", " ", ""], + ]) +); \ No newline at end of file diff --git a/soluciones-javascript/19-tres-en-raya/index.html b/soluciones-javascript/19-tres-en-raya/index.html new file mode 100644 index 000000000..b2229bbb8 --- /dev/null +++ b/soluciones-javascript/19-tres-en-raya/index.html @@ -0,0 +1,12 @@ + + + + + + Tres en raya + + +

Abre la consola y Visualiza el Resultado

+ + + \ No newline at end of file diff --git a/soluciones-javascript/20-conversor-tiempo/app.js b/soluciones-javascript/20-conversor-tiempo/app.js new file mode 100644 index 000000000..e23785be9 --- /dev/null +++ b/soluciones-javascript/20-conversor-tiempo/app.js @@ -0,0 +1,24 @@ +/* + * Crea una función que reciba días, horas, minutos y segundos (como enteros) + * y retorne su resultado en milisegundos. + */ + +const conversorTiempo = (dias, horas, minutos, segundos) => { + + if ( + typeof dias !== "number" || dias < 0 || + typeof horas !== "number" || dias < 0 || + typeof minutos !== "number" || dias < 0|| + typeof segundos !== "number" || dias < 0 + ) + throw new Error("Los datos deben ser númericos y mayor o igual a cero"); + + const diasASegundos = (((dias * 24) * 60) * 60); + const horasASegundos = ((horas * 60) * 60); + const minutosASegundos = ((minutos * 60)); + + return ( (diasASegundos + horasASegundos + minutosASegundos) * 1000 ); + +} + +console.log(conversorTiempo(1,1,1,1)); \ No newline at end of file diff --git a/soluciones-javascript/20-conversor-tiempo/index.html b/soluciones-javascript/20-conversor-tiempo/index.html new file mode 100644 index 000000000..a7195497f --- /dev/null +++ b/soluciones-javascript/20-conversor-tiempo/index.html @@ -0,0 +1,12 @@ + + + + + + Conversor de Tiempo + + +

Abre la consola y mira

+ + + \ No newline at end of file diff --git a/soluciones-javascript/21-parando-el-tiempo/app.js b/soluciones-javascript/21-parando-el-tiempo/app.js new file mode 100644 index 000000000..03449e264 --- /dev/null +++ b/soluciones-javascript/21-parando-el-tiempo/app.js @@ -0,0 +1,33 @@ +/* + * Crea una función que sume 2 números y retorne su resultado pasados + * unos segundos. + * - Recibirá por parámetros los 2 números a sumar y los segundos que + * debe tardar en finalizar su ejecución. + * - Si el lenguaje lo soporta, deberá retornar el resultado de forma + * asíncrona, es decir, sin detener la ejecución del programa principal. + * Se podría ejecutar varias veces al mismo tiempo. + */ + +/** + * Función que suma dos números y que los devuelve en cierto intervalo de tiempo + * @param {Number} num1 Numero 1 que recibe la función + * @param {Number} num2 Numero 2 que recibe la función + * @param {Number} segundosFinalizar Numero de tiempo en segundos + * @returns Resultado De numeros + */ +const parandoElTiempo = async (num1, num2, segundosFinalizar) => { + const suma = new Promise((resolve) => { + setTimeout(() => { + return resolve(num1 + num2); + }, segundosFinalizar * 1000); + }); + return await suma; +} + +parandoElTiempo(2, 3, 3).then((resultado) => + console.log(`Resultado de 2 + 3 después de 3 segundos: ${resultado}`) +); + +parandoElTiempo(5, 7, 2).then((resultado) => + console.log(`Resultado de 5 + 7 después de 2 segundos: ${resultado}`) +); \ No newline at end of file diff --git a/soluciones-javascript/21-parando-el-tiempo/index.html b/soluciones-javascript/21-parando-el-tiempo/index.html new file mode 100644 index 000000000..d659e7ea7 --- /dev/null +++ b/soluciones-javascript/21-parando-el-tiempo/index.html @@ -0,0 +1,12 @@ + + + + + + Parando el Tiempo + + +

Abre la consola y mira

+ + + \ No newline at end of file diff --git a/soluciones-javascript/22-calculadora-txt/Challenge21.txt b/soluciones-javascript/22-calculadora-txt/Challenge21.txt new file mode 100644 index 000000000..d5b2bd7c1 --- /dev/null +++ b/soluciones-javascript/22-calculadora-txt/Challenge21.txt @@ -0,0 +1,13 @@ +5 ++ +2 +- +1 +* +8 +- +15 ++ +4 +/ +2 \ No newline at end of file diff --git a/soluciones-javascript/22-calculadora-txt/index.js b/soluciones-javascript/22-calculadora-txt/index.js new file mode 100644 index 000000000..de11ee0eb --- /dev/null +++ b/soluciones-javascript/22-calculadora-txt/index.js @@ -0,0 +1,55 @@ +/* + * Lee el fichero "Challenge21.txt" incluido en el proyecto, calcula su + * resultado e imprímelo. + * - El .txt se corresponde con las entradas de una calculadora. + * - Cada línea tendrá un número o una operación representada por un + * símbolo (alternando ambos). + * - Soporta números enteros y decimales. + * - Soporta las operaciones suma "+", resta "-", multiplicación "*" + * y división "/". + * - El resultado se muestra al finalizar la lectura de la última + * línea (si el .txt es correcto). + * - Si el formato del .txt no es correcto, se indicará que no se han + * podido resolver las operaciones. + */ + +const fs = require("fs"); + +try { + const data = fs.readFileSync("./Challenge21.txt", "utf-8"); + const lines = data.split("\r\n").filter((line) => line.trim() !== ""); + + console.log({ lines }); + + let resultado = Number(lines[0]); + + for (let i = 1; i < lines.length; i += 2) { + let operacion = lines[i]; + let numero = Number(lines[i + 1]); + + if (isNaN(numero)) { + return "Error al Leer el dato"; + } + + switch (operacion) { + case "+": + resultado += numero; + break; + case "-": + resultado -= numero; + break; + case "*": + resultado *= numero; + break; + case "/": + resultado /= numero; + break; + default: + return resultado; + } + } + + console.log({ resultado }); +} catch (err) { + console.error("Error al leer el archivo:", err); +} diff --git a/soluciones-javascript/23-conjuntos/index.js b/soluciones-javascript/23-conjuntos/index.js new file mode 100644 index 000000000..91dfcb668 --- /dev/null +++ b/soluciones-javascript/23-conjuntos/index.js @@ -0,0 +1,50 @@ +/* + * Crea una función que reciba dos array, un booleano y retorne un array. + * - Si el booleano es verdadero buscará y retornará los elementos comunes + * de los dos array. + * - Si el booleano es falso buscará y retornará los elementos no comunes + * de los dos array. + * - No se pueden utilizar operaciones del lenguaje que + * lo resuelvan directamente. + */ + +/** + * Función que determina los iguales o no iguales de dos arrays dependiendo del valor del booleano + * @param {Array} arr1 Array de valores + * @param {Array} arr2 Array de valores + * @param {Boolean} boolean Variable que determina el flujo de la función + */ +const conjuntos = (arr1, arr2, boolean) => { + const resultado = []; + + if (boolean) { + for (let i = 0; i < arr1.length; i++) { + for (let j = 0; j < arr2.length; j++) { + if (arr1[i] === arr2[j]) { + if (!resultado.includes(arr1[i]) || !resultado.includes(arr2[j])) { + resultado.push(arr1[i]); + } + } + } + } + } else { + for (let i = 0; i < arr1.length; i++) { + for (let j = 0; j < arr2.length; j++) { + if (arr1[i] !== arr2[j]) { + if (!resultado.includes(arr1[i]) || !resultado.includes(arr2[j])) { + if (!arr1.includes(arr2[j]) && !resultado.includes(arr2[j])) { + resultado.push(arr2[j]); + } else if (!arr2.includes(arr1[i]) && !resultado.includes(arr1[i])) { + resultado.push(arr1[i]); + } + } + } + } + } + } + + return resultado; +}; + +console.log(conjuntos([1, 23, 4, 56, 7, 89, 10], [1, 23, 4, 5, 6, 67, 8, 1, 210, 10], true)); +console.log(conjuntos([1, 23, 4, 56, 7, 89, 10], [1, 23, 4, 5, 6, 67, 8, 1, 210, 10], false)); diff --git a/soluciones-javascript/24-maximo-comun-divisor-minimo-comun-multiplo/index.js b/soluciones-javascript/24-maximo-comun-divisor-minimo-comun-multiplo/index.js new file mode 100644 index 000000000..91612ff54 --- /dev/null +++ b/soluciones-javascript/24-maximo-comun-divisor-minimo-comun-multiplo/index.js @@ -0,0 +1,19 @@ +/* + * Crea dos funciones, una que calcule el máximo común divisor (MCD) y otra + * que calcule el mínimo común múltiplo (mcm) de dos números enteros. + * - No se pueden utilizar operaciones del lenguaje que + * lo resuelvan directamente. + */ + +const mcd = (a , b) => { + return b === 0 ? a : mcd(b, a % b); +} + +const mcm = (a , b) => { + return ( a * b ) / mcd(a,b); +} + +console.log(mcd(48, 36)); +console.log(mcd(12, 18)); +console.log(mcm(12, 18)); +console.log(mcm(48, 36)); diff --git a/soluciones-javascript/25-iteration-master/index.js b/soluciones-javascript/25-iteration-master/index.js new file mode 100644 index 000000000..6071d168d --- /dev/null +++ b/soluciones-javascript/25-iteration-master/index.js @@ -0,0 +1,44 @@ +/* + * Quiero contar del 1 al 100 de uno en uno (imprimiendo cada uno). + * ¿De cuántas maneras eres capaz de hacerlo? + * Crea el código para cada una de ellas. + */ + + +/** + * Función que imprime números de 1 al 100 + * @param {Number} forma: 1: 'for' | 2: 'while' | 3: 'Recursividad' + */ +const iterationMaster = (forma) => { + + if(forma === 1){ + + for (let i = 1; i <= 100; i++) { + console.log(i); + } + + } else if ( forma === 2 ) { + let i = 1; + while (i <= 100) { + console.log(i); + i++; + } + } else if( forma === 3 ) { + + const imprimirRecursivamente = (i = 1) => { + if ( i > 100 ) return; + console.log(i); + imprimirRecursivamente( i + 1); + } + + imprimirRecursivamente(); + }else { + console.log('No hay forma con dicho parametro'); + } + +} + + +// iterationMaster(1); +//iterationMaster(2); +iterationMaster(3); diff --git a/soluciones-javascript/26-piedra-papel-tijera/index.js b/soluciones-javascript/26-piedra-papel-tijera/index.js new file mode 100644 index 000000000..575841b86 --- /dev/null +++ b/soluciones-javascript/26-piedra-papel-tijera/index.js @@ -0,0 +1,66 @@ +/* + * Crea un programa que calcule quien gana más partidas al piedra, + * papel, tijera. + * - El resultado puede ser: "Player 1", "Player 2", "Tie" (empate) + * - La función recibe un listado que contiene pares, representando cada jugada. + * - El par puede contener combinaciones de "R" (piedra), "P" (papel) + * o "S" (tijera). + * - Ejemplo. Entrada: [("R","S"), ("S","R"), ("P","S")]. Resultado: "Player 2". + */ + +/** + * Juego de piedra papel o tijera + * @param {Array>} jugadas - Lista de pares de jugadas, donde cada par es ["R", "P", "S"] + * @return {string} - "Player 1", "Player 2" o "Tie" + */ +const piedraPapelTijera = (jugadas) => { + + const puntaje = { + player1: 0, + player2: 0, + } + + const reglas = { + R: "S", + P: "R", + S: "P" + }; + + jugadas.forEach(([p1, p2]) => { + + if ( reglas[p1] === p2 ){ + puntaje.player1++; + } else if ( reglas[p2] === p1 ) { + puntaje.player2++; + } + + }); + + const { player1, player2 } = puntaje; + + return (player1 > player2) ? "Player 1" : + (player2 > player1) ? "Player 2" : "Tie"; + +} + +// 1 +console.log(piedraPapelTijera([ + ["R", "S"], + ["S", "R"], + ["P", "S"], +])); + +// 2 +console.log(piedraPapelTijera([ + ["S", "P"], + ["S", "R"], + ["P", "R"], +])); + +// Tie +console.log(piedraPapelTijera([ + ["R", "S"], + ["S", "R"], + ["P", "S"], + ["S", "P"], +])); \ No newline at end of file diff --git a/soluciones-javascript/27-cuadrado-y-triangulo-2d/index.js b/soluciones-javascript/27-cuadrado-y-triangulo-2d/index.js new file mode 100644 index 000000000..4e6e40b76 --- /dev/null +++ b/soluciones-javascript/27-cuadrado-y-triangulo-2d/index.js @@ -0,0 +1,74 @@ +/* + * Crea un programa que dibuje un cuadrado o un triángulo con asteriscos "*". + * - Indicaremos el tamaño del lado y si la figura a dibujar es una u otra. + * - EXTRA: ¿Eres capaz de dibujar más figuras? + */ + +/** + * + * @param {*} size + * @param {*} type + */ +const dibujarFigurasGeometricas = (size, type) => { + if (size < 2) throw new Error("El tamaño debe ser 2 o mayor a 2"); + + switch (type) { + case "cuadrado": + dibujarCuadrado(size); + break; + case "triangulo": + dibujarTriangulo(size); + break; + case "rombo": + dibujarRombo(size); + break; + default: + console.log("Tamaño ingresado no existe, ingrese cuadrado - triangulo - rombo"); + break; + } +}; + +const dibujarCuadrado = (size) => { + + const linea = "* ".repeat(size); + + for (let i = 0; i < size; i++) { + + console.log(linea); + + } + +} + +const dibujarTriangulo = (size) => { + + for (let i = 0; i <= size; i++) { + + console.log( " ".repeat(size - i) + "* ".repeat(i)); + + } + +} + +const dibujarRombo = (size) => { + + if ( size % 2 === 0){ + console.log("El tamaño del rombo debe ser impar"); + return; + } + + let half = Math.floor( size / 2 ); + + for (let i = 0; i <= half; i++) { + console.log(" ".repeat(half - i) + "* ".repeat(i + 1)); + } + + for (let i = half - 1; i >= 0; i--) { + console.log(" ".repeat(half - i) + "* ".repeat(i + 1)); + } + +} + +dibujarFigurasGeometricas(11, 'rombo'); +dibujarFigurasGeometricas(6, 'triangulo'); +dibujarFigurasGeometricas(6, 'cuadrado'); \ No newline at end of file diff --git a/soluciones-javascript/28-vectores-ortogonales/index.js b/soluciones-javascript/28-vectores-ortogonales/index.js new file mode 100644 index 000000000..5fed7595c --- /dev/null +++ b/soluciones-javascript/28-vectores-ortogonales/index.js @@ -0,0 +1,29 @@ +/* + * Crea un programa que determine si dos vectores son ortogonales. + * - Los dos array deben tener la misma longitud. + * - Cada vector se podría representar como un array. Ejemplo: [1, -2] + */ + +/** + * + * @param {Array} vectorA + * @param {Array} vectorB + * @returns boolean + */ +const esVectorOrtogonal = (vectorA, vectorB) => { + + if ( vectorA.length !== vectorB.length ) throw new Error("Los Vectores deben tener la misma longitud"); + + let productoEscalar = 0; + + vectorA.forEach( (vector, index) => { + productoEscalar += ( vector * vectorB[index]); + }); + + return productoEscalar === 0; + +} + +// Ejemplo de uso: +console.log(esVectorOrtogonal([1, -2], [2, 1])); // true (son ortogonales) +console.log(esVectorOrtogonal([1, 2, 3], [4, 5, 6])); // false (no son ortogonales) \ No newline at end of file diff --git a/soluciones-javascript/29-maquina-expendedora/index.js b/soluciones-javascript/29-maquina-expendedora/index.js new file mode 100644 index 000000000..4de05e1d1 --- /dev/null +++ b/soluciones-javascript/29-maquina-expendedora/index.js @@ -0,0 +1,98 @@ +/* + * Simula el funcionamiento de una máquina expendedora creando una operación + * que reciba dinero (array de monedas) y un número que indique la selección + * del producto. + * - El programa retornará el nombre del producto y un array con el dinero + * de vuelta (con el menor número de monedas). + * - Si el dinero es insuficiente o el número de producto no existe, + * deberá indicarse con un mensaje y retornar todas las monedas. + * - Si no hay dinero de vuelta, el array se retornará vacío. + * - Para que resulte más simple, trabajaremos en céntimos con monedas + * de 5, 10, 50, 100 y 200. + * - Debemos controlar que las monedas enviadas estén dentro de las soportadas. + */ + +const productos = [ + { codigo: "A1", nombre: "Papitas de Pollo", precio: 100 }, + { codigo: "A3", nombre: "Doritos dinamita", precio: 100 }, + { codigo: "B1", nombre: "agua", precio: 10 }, + { codigo: "B2", nombre: "agua con gas", precio: 100 }, + { codigo: "B3", nombre: "agua con sabor a fresa", precio: 100 }, + { codigo: "C1", nombre: "Gomitas", precio: 100 }, + { codigo: "C2", nombre: "Trululu", precio: 100 }, + { codigo: "C3", nombre: "gomitas acidas", precio: 100 }, + { codigo: "D1", nombre: "Coca Cola", precio: 200 }, + { codigo: "D2", nombre: "Fanta", precio: 200 }, + { codigo: "D3", nombre: "Sprite", precio: 200 }, + { codigo: "E1", nombre: "Margaritas Naturales", precio: 100 }, + { codigo: "E2", nombre: "Margaritas Picantes", precio: 100 }, + { codigo: "E3", nombre: "Doritos", precio: 100 }, +]; + +const monedasSoportadas = [5, 10, 50, 100, 200]; + +const calcularCambio = (cambio) => { + let resultado = []; + + for (let moneda of monedasSoportadas.sort((a, b) => b - a)) { + while (cambio >= moneda) { + + resultado.push(moneda); + + cambio -= moneda; + } + } + + return resultado; +}; + +/** + * Simula el funcionamiento de una máquina expendedora. + * + * @param {Object} param0 - Objeto con la información del pedido. + * @param {number[]} param0.dinero - Array de monedas ingresadas en la máquina. + * @param {string} param0.seleccionProducto - Código del producto seleccionado. + * @returns {string|Object} Mensaje de error o un objeto con el producto y el cambio. + */ +const maquinaExpendedora = ({ dinero, seleccionProducto }) => { + // Validar que todas las monedas ingresadas sean soportadas + if (!dinero.every((m) => monedasSoportadas.includes(m))) { + return "Error: Se han Ingresado monedas no soportadas. Se devuelve el dinero"; + } + + const producto = productos.find((p) => p.codigo === seleccionProducto); + + const dineroTotal = dinero.reduce((acc, moneda) => acc + moneda, 0); + + // Si el producto no existe, devolver dinero + if (!producto) { + return "Error: Producto no encontrado. Se devuelve el dinero."; + } + + // Si el dinero es insuficiente, devolver dinero + if (dineroTotal < producto.precio) { + return "Error: Dinero insuficiente. Se devuelve el dinero."; + } + + const cambio = calcularCambio(dineroTotal - producto.precio); + + return { + producto: producto.nombre, + cambio + }; +}; + +console.log(maquinaExpendedora({ dinero: [100, 50, 50], seleccionProducto: "A1" })); +// { producto: 'Papitas de Pollo', cambio: [100] } + +console.log(maquinaExpendedora({ dinero: [5, 10, 50], seleccionProducto: "B1" })); +// { producto: 'Agua', cambio: [50, 10, 5] } + +console.log(maquinaExpendedora({ dinero: [100, 100], seleccionProducto: "D1" })); +// { producto: 'Coca Cola', cambio: [] } + +console.log(maquinaExpendedora({ dinero: [200], seleccionProducto: "Z1" })); +// "Error: Producto no encontrado. Se devuelve el dinero." + +console.log(maquinaExpendedora({ dinero: [500], seleccionProducto: "A1" })); +// "Error: Se han ingresado monedas no soportadas. Se devuelve el dinero." diff --git a/soluciones-javascript/30-ordena-lista/index.js b/soluciones-javascript/30-ordena-lista/index.js new file mode 100644 index 000000000..cf8134f0e --- /dev/null +++ b/soluciones-javascript/30-ordena-lista/index.js @@ -0,0 +1,61 @@ +/* + * Crea una función que ordene y retorne una matriz de números. + * - La función recibirá un listado (por ejemplo [2, 4, 6, 8, 9]) y un parámetro + * adicional "Asc" o "Desc" para indicar si debe ordenarse de menor a mayor + * o de mayor a menor. + * - No se pueden utilizar funciones propias del lenguaje que lo resuelvan + * automáticamente. + */ + +const ordenarAsc = (lista) => { + let n = lista.length; + for (let i = 0; i < n - 1; i++) { + for (let j = 0; j < n - i - 1; j++) { + if (lista[j] > lista[j + 1]) { + let temp = lista[j]; + lista[j] = lista[j + 1]; + lista[j + 1] = temp; + } + } + } + return lista; +}; + +const ordenarDesc = (lista) => { + let n = lista.length; + for (let i = 0; i < n - 1; i++) { + for (let j = 0; j < n - i - 1; j++) { + if (lista[j] < lista[j + 1]) { + let temp = lista[j]; + lista[j] = lista[j + 1]; + lista[j + 1] = temp; + } + } + } + return lista; +}; +/** + * Función para ordenar un array de números + * @param {Array} lista + * @return ArrayOrdenado + */ +const ordenarLista = ( lista, indicacion ) => { + + if ( !lista.every((num) => typeof num === "number" )){ + return "Error: los elementos del array no son un número" + }; + + switch (indicacion) { + case "Asc": + return ordenarAsc([...lista]); + case "Desc": + return ordenarDesc([...lista]); + default: + return "Error: indicación no válida"; + } + +} + +// Pruebas +console.log(ordenarLista([5, 2, 9, 1, 5, 6], "Asc")); // [1, 2, 5, 5, 6, 9] +console.log(ordenarLista([3, 8, 2, 7, 4], "Desc")); // [8, 7, 4, 3, 2] diff --git a/soluciones-javascript/31-marco-de-palabras/index.js b/soluciones-javascript/31-marco-de-palabras/index.js new file mode 100644 index 000000000..aad6fa653 --- /dev/null +++ b/soluciones-javascript/31-marco-de-palabras/index.js @@ -0,0 +1,38 @@ +/* + * Crea una función que reciba un texto y muestre cada palabra en una línea, + * formando un marco rectangular de asteriscos. + * - ¿Qué te parece el reto? Se vería así: + * ********** + * * ¿Qué * + * * te * + * * parece * + * * el * + * * reto? * + * ********** + */ + +/** + * + * @param {String} sentence + */ +const marcoDePalabras = (sentence) => { + + const sentenceLengthMajor = Math.max(...sentence.split(/[^A-Za-zÁ-Úá-úÜüÑñ]+/).map( element => element.length)); + + const inicioFinMarco = "*".repeat(sentenceLengthMajor + 4); + + + const palabrasSeparadas = inicioFinMarco + "\n" + sentence.trim().split(' ').map( word => { + + const espacios = word.length === sentenceLengthMajor ? 0 : sentenceLengthMajor - word.length; + + return "* " + word + " ".repeat(espacios + 1) + "*"; + }).join('\n').concat("\n" + inicioFinMarco); + + console.log(palabrasSeparadas); + +} + +marcoDePalabras("¿Qué te parece el reto?"); +marcoDePalabras("Esto es otro ejemplo más"); +marcoDePalabras("Esto es una declaración de amor"); \ No newline at end of file diff --git "a/soluciones-javascript/32-a\303\261os-bisiestos/index.js" "b/soluciones-javascript/32-a\303\261os-bisiestos/index.js" new file mode 100644 index 000000000..02084f308 --- /dev/null +++ "b/soluciones-javascript/32-a\303\261os-bisiestos/index.js" @@ -0,0 +1,37 @@ +/* + * Crea una función que imprima los 30 próximos años bisiestos + * siguientes a uno dado. + * - Utiliza el menor número de líneas para resolver el ejercicio. + */ + +const esBisiesto = (year) => { + return ((year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0)); +} + +const calcularBisiesto = (year) => { + + if (!esBisiesto(year)) { + return "Error: debes ingresar un año bisiesto" + } + + const proximosBisiestos = []; + + for (let i = 1; i <= 30; i++) { + + year += 4; + + if (esBisiesto(year)) { + proximosBisiestos.push(year); + } else { + i--; + } + + } + + return proximosBisiestos; + +} + +console.log(calcularBisiesto(2024)); +console.log(calcularBisiesto(2000)); +console.log(calcularBisiesto(1900)); \ No newline at end of file diff --git a/soluciones-javascript/33-el-segundo/index.js b/soluciones-javascript/33-el-segundo/index.js new file mode 100644 index 000000000..6c8aa917f --- /dev/null +++ b/soluciones-javascript/33-el-segundo/index.js @@ -0,0 +1,23 @@ +/* + * Dado un listado de números, encuentra el SEGUNDO más grande + */ + +/** + * + * @param {Array} lista + */ +const elSegundoMasGrande = (lista) => { + + const listaFormateada = lista.filter( (value, index, array) => array.indexOf(value) === index); + + listaFormateada.sort((a, b) => b - a ).shift(); + + return listaFormateada.shift(); + +} + +console.log(elSegundoMasGrande([1,98,2,4,56,8,9,55])); +console.log(elSegundoMasGrande([100, 100, 50])); // Retorna 50 (Correcto) +console.log(elSegundoMasGrande([100, 100])); // Retorna 100 (Incorrecto, debería ser undefined o indicar que no hay segundo más grande) +console.log(elSegundoMasGrande([42])); // Retorna undefined (No hay segundo más grande) +console.log(elSegundoMasGrande([])); // Retorna undefined (Correcto, pero podría manejarse mejor) diff --git a/soluciones-javascript/34-ciclo-sexagenario-chino/index.js b/soluciones-javascript/34-ciclo-sexagenario-chino/index.js new file mode 100644 index 000000000..c0134d11a --- /dev/null +++ b/soluciones-javascript/34-ciclo-sexagenario-chino/index.js @@ -0,0 +1,37 @@ +/* + * Crea un función, que dado un año, indique el elemento + * y animal correspondiente en el ciclo sexagenario del zodíaco chino. + * - Info: https://www.travelchinaguide.com/intro/astrology/60year-cycle.htm + * - El ciclo sexagenario se corresponde con la combinación de los elementos + * madera, fuego, tierra, metal, agua y los animales rata, buey, tigre, + * conejo, dragón, serpiente, caballo, oveja, mono, gallo, perro, cerdo + * (en este orden). + * - Cada elemento se repite dos años seguidos. + * - El último ciclo sexagenario comenzó en 1984 (Madera Rata). + */ + +const cicloSexagenarioChino = (year) => { + + const elements = [ "madera", "fuego", "tierra", "metal", "agua" ]; + const animals = [ "rata", "buey", "tigre", "conejo", "dragón", "serpiente", "caballo", "oveja", "mono", "gallo", "perro", "cerdo"]; + + if ( year < 604) { + return "El ciclo sexagenario comenzó en el año 604"; + } + + const sexagenaryYear = Math.floor((year - 4) % 60); + const elementsYear = elements[Math.floor((sexagenaryYear % 10) / 2)]; + const animalsYear = animals[Math.floor(sexagenaryYear % 12)]; + + + return `El año ${year}: ${elementsYear} ${animalsYear}`; + +} + +console.log(cicloSexagenarioChino(1924)); +console.log(cicloSexagenarioChino(1946)); +console.log(cicloSexagenarioChino(1984)); +console.log(cicloSexagenarioChino(604)); +console.log(cicloSexagenarioChino(603)); +console.log(cicloSexagenarioChino(1987)); +console.log(cicloSexagenarioChino(2022)); \ No newline at end of file diff --git a/soluciones-javascript/35-los-numeros-perdidos/index.js b/soluciones-javascript/35-los-numeros-perdidos/index.js new file mode 100644 index 000000000..3d5989921 --- /dev/null +++ b/soluciones-javascript/35-los-numeros-perdidos/index.js @@ -0,0 +1,50 @@ +/* + * Dado un array de enteros ordenado y sin repetidos, + * crea una función que calcule y retorne todos los que faltan entre + * el mayor y el menor. + * - Lanza un error si el array de entrada no es correcto. + */ + +/** + * + * @param {Array} array + */ +const numerosPerdidos = (array) => { + + if (!Array.isArray(array)) throw new Error("El parámetro debe ser un array."); + if (array.length === 0) throw new Error("El array no debe estar vacío."); + if (!array.every(num => Number.isInteger(num))) throw new Error("Todos los elementos deben ser números enteros."); + + // Verificar si el array está ordenado de menor a mayor + for (let i = 0; i < array.length - 1; i++) { + if (array[i] >= array[i + 1]) { + return "El array debe estar ordenado de menor a mayor y sin repetidos."; + } + } + + const numerosFaltantes = []; + + for (let i = 0; i < array.length; i++) { + + const numeroSuperior = array[i + 1] || 0; + + if ( (numeroSuperior - array[i]) > 1){ + const diferencial = (numeroSuperior - array[i]); + + for (let j = 1; j < diferencial; j++) { + numerosFaltantes.push(numeroSuperior - (diferencial - j)); + } + + } + + } + + return numerosFaltantes; + +} + +// Pruebas +console.log(numerosPerdidos([1, 3, 4, 7])); // [2, 5, 6] +console.log(numerosPerdidos([1, 4, 10])); // [2, 3, 5, 6, 7, 8, 9] +console.log(numerosPerdidos([5, 6, 8, 17, 20])); // [7, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19] +console.log(numerosPerdidos([1, 2, 3, 4, 5])); // [] \ No newline at end of file diff --git a/soluciones-javascript/36-batalla-pokemon/index.js b/soluciones-javascript/36-batalla-pokemon/index.js new file mode 100644 index 000000000..2a0915dea --- /dev/null +++ b/soluciones-javascript/36-batalla-pokemon/index.js @@ -0,0 +1,38 @@ +/* + * Crea un programa que calcule el daño de un ataque durante + * una batalla Pokémon. + * - La fórmula será la siguiente: daño = 50 * (ataque / defensa) * efectividad + * - Efectividad: x2 (súper efectivo), x1 (neutral), x0.5 (no es muy efectivo) + * - Sólo hay 4 tipos de Pokémon: Agua, Fuego, Planta y Eléctrico + * (buscar su efectividad) + * - El programa recibe los siguientes parámetros: + * - Tipo del Pokémon atacante. + * - Tipo del Pokémon defensor. + * - Ataque: Entre 1 y 100. + * - Defensa: Entre 1 y 100. + */ + +const tiposDeEfectividad = { + agua: { fuego: 2, planta: 0.5, electrico: 0.5, agua: 1 }, + fuego: { planta: 2, agua: 0.5, electrico: 1, fuego: 1 }, + planta: { agua: 2, fuego: 0.5, electrico: 0.5, planta: 1 }, + electrico: { agua: 2, planta: 0.5, fuego: 1, electrico: 1 }, +} + +const calcularDamageInBattle = (tipoAtacante, tipoDefensor, ataque, defensa) => { + + if (!tiposDeEfectividad[tipoAtacante] || !tiposDeEfectividad[tipoAtacante][tipoDefensor]) { + throw new Error("Tipo de Pokémon inválido"); + } + + const tipoEfectividad = tiposDeEfectividad[tipoAtacante][tipoDefensor]; + + return 50 * ( ataque / defensa ) * tipoEfectividad; + + +} + +console.log(calcularDamageInBattle("agua", "electrico", 40, 70)); +console.log(calcularDamageInBattle("agua", "fuego", 80, 50)); // Daño esperado alto (súper efectivo) +console.log(calcularDamageInBattle("fuego", "agua", 60, 70)); // Daño esperado bajo (no muy efectivo) +console.log(calcularDamageInBattle("planta", "planta", 90, 90)); // Daño esperado neutro (x1) \ No newline at end of file diff --git a/soluciones-javascript/37-los-anillos-del-poder/index.js b/soluciones-javascript/37-los-anillos-del-poder/index.js new file mode 100644 index 000000000..9cbfe9b6e --- /dev/null +++ b/soluciones-javascript/37-los-anillos-del-poder/index.js @@ -0,0 +1,83 @@ +/* + * ¡La Tierra Media está en guerra! En ella lucharán razas leales + * a Sauron contra otras bondadosas que no quieren que el mal reine + * sobre sus tierras. + * Cada raza tiene asociado un "valor" entre 1 y 5: + * - Razas bondadosas: Pelosos (1), Sureños buenos (2), Enanos (3), + * Númenóreanos (4), Elfos (5) + * - Razas malvadas: Sureños malos (2), Orcos (2), Goblins (2), + * Huargos (3), Trolls (5) + * Crea un programa que calcule el resultado de la batalla entre + * los 2 tipos de ejércitos: + * - El resultado puede ser que gane el bien, el mal, o exista un empate. + * Dependiendo de la suma del valor del ejército y el número de integrantes. + * - Cada ejército puede estar compuesto por un número de integrantes variable + * de cada raza. + * - Tienes total libertad para modelar los datos del ejercicio. + * Ej: 1 Peloso pierde contra 1 Orco + * 2 Pelosos empatan contra 1 Orco + * 3 Pelosos ganan a 1 Orco + */ + +const razasBondadosas = { + pelosos: 1, + sureniosBuenos: 2, + enanos: 3, + numenoreanos: 4, + elfos: 5 +} + +const razasMalvadas = { + sureniosMalosMalos: 2, + orcos: 2, + goblins: 2, + huargos: 3, + trolls: 5 +} + +const calculoRazaVencedora = ( ejercitoBondadoso, ejercitoMalvado ) => { + let puntosBondadosos = 0; + let puntosMalvados = 0; + + ejercitoBondadoso.forEach(raza => { + const [ nombre, cantidad ] = Object.entries(raza)[0]; + + if( razasBondadosas[nombre]) { + puntosBondadosos += razasBondadosas[nombre] * cantidad; + } + }); + + ejercitoMalvado.forEach(raza => { + const [ nombre, cantidad] = Object.entries(raza)[0]; + + if( razasMalvadas[nombre]) { + puntosMalvados += razasMalvadas[nombre] * cantidad; + }; + }); + + + return puntosBondadosos > puntosMalvados + ? 'El bien triunfa sobre el mal' + : puntosMalvados > puntosBondadosos + ? 'El mal triunfa sobre el bien' + : 'La batalla fue un empate'; + +} + +const ejercitoBondadoso = [ + {pelosos: 2,}, + {sureniosBuenos: 3,}, + {enanos: 4, }, + {numenoreanos: 2, }, + {elfos: 5,}, +]; +const ejercitoMalvado = [ + {sureniosMalosMalos: 2,} , + {orcos: 2, }, + {goblins: 2,}, + {huargos: 3, }, + {trolls: 5}, +]; + + +console.log(calculoRazaVencedora(ejercitoBondadoso, ejercitoMalvado)); \ No newline at end of file diff --git a/soluciones-javascript/38-lanzamientos-legend-of-zelda/index.js b/soluciones-javascript/38-lanzamientos-legend-of-zelda/index.js new file mode 100644 index 000000000..3c3d63484 --- /dev/null +++ b/soluciones-javascript/38-lanzamientos-legend-of-zelda/index.js @@ -0,0 +1,54 @@ +/* + * ¡Han anunciado un nuevo "The Legend of Zelda"! + * Se llamará "Tears of the Kingdom" y se lanzará el 12 de mayo de 2023. + * Pero, ¿recuerdas cuánto tiempo ha pasado entre los distintos + * "The Legend of Zelda" de la historia? + * Crea un programa que calcule cuántos años y días hay entre 2 juegos de Zelda + * que tú selecciones. + * - Debes buscar cada uno de los títulos y su día de lanzamiento + * (si no encuentras el día exacto puedes usar el mes, o incluso inventártelo) + */ + +/** + * Compara dos juegos en función de su nombre y año de lanzamiento. + * + * @param {{ name: string, releaseYear: string }} juego1 - Primer juego a comparar. + * @param {{ name: string, releaseYear: string }} juego2 - Segundo juego a comparar. + */ +const lanzamientosLegendOfZelda = (juego1, juego2) => { + const { name, releaseYear } = juego1; + const { name: name2, releaseYear: releaseYear2 } = juego2; + + const fechaJuego1 = new Date(releaseYear); + const fechaJuego2 = new Date(releaseYear2); + + let anios = fechaJuego2.getFullYear() - fechaJuego1.getFullYear() ; + let meses = fechaJuego2.getMonth() - fechaJuego1.getMonth(); + let dias = fechaJuego2.getDate() - fechaJuego1.getDate(); + + if ( dias < 0){ + meses--; + const mesAnterior = new Date(fechaJuego2.getFullYear(), fechaJuego2.getMonth(), 0); + dias += mesAnterior.getDate(); + } + + if (meses < 0) { + anios--; + meses += 12; + } + + console.log( { anios, meses, dias } ); + + +}; + +lanzamientosLegendOfZelda( + { + name: "The Legend of Zelda: Ocarina of Time", + releaseYear: "12/11/1998", + }, + { + name: "Zelda: Majoras Mask", + releaseYear: "11/17/2000", + } +); diff --git a/soluciones-javascript/39-binario-a-decimal/index.js b/soluciones-javascript/39-binario-a-decimal/index.js new file mode 100644 index 000000000..6c92f8b5c --- /dev/null +++ b/soluciones-javascript/39-binario-a-decimal/index.js @@ -0,0 +1,31 @@ +/* + * Crea un programa se encargue de transformar un número binario + * a decimal sin utilizar funciones propias del lenguaje que + * lo hagan directamente. + */ + +/** + * + * @param {Number} numeroBinario + */ +const binaryToDecimal = (numeroBinario) => { + + const stringNumeroBinario = numeroBinario.toString(); + let resultado = 0; + let exponente = 0; + + for (let i = 1; i <= stringNumeroBinario.length; i++) { + + const number = Number(stringNumeroBinario[ stringNumeroBinario.length - i]); + + resultado += (number * Math.pow(2, exponente)); + exponente++; + } + + return resultado; + +} + +console.log(binaryToDecimal(1011)); +console.log(binaryToDecimal(1010)); +console.log(binaryToDecimal(11111111)); \ No newline at end of file diff --git a/soluciones-javascript/40-top-algoritmos/index.js b/soluciones-javascript/40-top-algoritmos/index.js new file mode 100644 index 000000000..625d4c20c --- /dev/null +++ b/soluciones-javascript/40-top-algoritmos/index.js @@ -0,0 +1,41 @@ +/* + * Implementa uno de los algoritmos de ordenación más famosos: + * el "Quick Sort", creado por C.A.R. Hoare. + * - Entender el funcionamiento de los algoritmos más utilizados de la historia + * Nos ayuda a mejorar nuestro conocimiento sobre ingeniería de software. + * Dedícale tiempo a entenderlo, no únicamente a copiar su implementación. + * - Esta es una nueva serie de retos llamada "TOP ALGORITMOS", + * donde trabajaremos y entenderemos los más famosos de la historia. + */ + +/** + * + * @param {Array} array + */ +const quickSort = (array) => { + + if (array.length <= 1 ) { + return array; + } + + const pivot = array[array.length - 1]; + const left = []; + const right = []; + + for (let i = 0; i < array.length - 1; i++) { + + if (array[i] < pivot ) { + left.push(array[i]); + } else{ + right.push(array[i]); + } + + } + + console.log({left, right}) + + return [ ...quickSort(left), pivot, ...quickSort(right) ]; + +} + +console.log(quickSort([ 8, 9, 3, 7, 1, 2, 6, 4])); \ No newline at end of file diff --git a/soluciones-javascript/41-triangulo-de-pascal/index.js b/soluciones-javascript/41-triangulo-de-pascal/index.js new file mode 100644 index 000000000..c51e3a012 --- /dev/null +++ b/soluciones-javascript/41-triangulo-de-pascal/index.js @@ -0,0 +1,41 @@ +/* + * Crea una función que sea capaz de dibujar el "Triángulo de Pascal" + * indicándole únicamente el tamaño del lado. + * + * - Aquí puedes ver rápidamente cómo se calcula el triángulo: + * https://commons.wikimedia.org/wiki/File:PascalTriangleAnimated2.gif + */ + +const generarTrianguloPascal = (n) => { + let triangulo = []; + + for (let i = 0; i < n; i++) { + triangulo[i] = []; + for (let j = 0; j <= i; j++) { + if (j === 0 || j === i) { + triangulo[i][j] = 1; + } else { + triangulo[i][j] = triangulo[i - 1][j - 1] + triangulo[i - 1][j]; + } + } + } + + return triangulo; +} + +const imprimirTrianguloPascal = (triangulo) => { + let n = triangulo.length; + let resultado = ""; + + for (let i = 0; i < n; i++) { + let espacio = " ".repeat(n - i); + let fila = triangulo[i].join(" "); + resultado += espacio + fila + "\n"; + } + + console.log(resultado); +} + +let n = 5; // Tamaño del triángulo +let triangulo = generarTrianguloPascal(n); +imprimirTrianguloPascal(triangulo); diff --git a/soluciones-javascript/42-la-ley-de-ohm/index.js b/soluciones-javascript/42-la-ley-de-ohm/index.js new file mode 100644 index 000000000..88c0cd6c3 --- /dev/null +++ b/soluciones-javascript/42-la-ley-de-ohm/index.js @@ -0,0 +1,37 @@ +/* + * Crea una función que calcule el valor del parámetro perdido + * correspondiente a la ley de Ohm. + * - Enviaremos a la función 2 de los 3 parámetros (V, R, I), y retornará + * el valor del tercero (redondeado a 2 decimales). + * - Si los parámetros son incorrectos o insuficientes, la función retornará + * la cadena de texto "Invalid values". + */ + +/** + * + * @param {{ v: Number, r: Number, i: Number }} param0 + */ +const leyDeOhm = ({ v, r, i }) => { + + const valores = [ v, r, i ]; + const faltantes = valores.filter( value => value === undefined ).length; + + if ( faltantes !== 1 || valores.some( value => value !== undefined && (typeof value !== "number") || value < 0)) + return "Invalid Values"; + + return v === undefined + ? (i * r).toFixed(2) + : r === undefined + ? (v / i).toFixed(2) + : i === undefined + ? (v / r).toFixed(2) + : 'Invalid values'; +} + +console.log(leyDeOhm({ v: 0, r: 2, i: 3 })); // "Invalid values" +console.log(leyDeOhm({ v: undefined, r: 4, i: 5 })); // 20.00 +console.log(leyDeOhm({ v: 12, r: undefined, i: 3 })); // 4.00 +console.log(leyDeOhm({ v: 12, r: 4, i: undefined })); // 3.00 +console.log(leyDeOhm({ v: 12, r: 4, i: 3 })); // "Invalid values" +console.log(leyDeOhm({ v: -12, r: 4, i: undefined })); // "Invalid values" +console.log(leyDeOhm({ v: 12, r: "4", i: undefined })); // "Invalid values" \ No newline at end of file diff --git a/soluciones-javascript/43-conversor-temperatura/index.js b/soluciones-javascript/43-conversor-temperatura/index.js new file mode 100644 index 000000000..6b0a4e670 --- /dev/null +++ b/soluciones-javascript/43-conversor-temperatura/index.js @@ -0,0 +1,44 @@ +/* + * Crea una función que transforme grados Celsius en Fahrenheit + * y viceversa. + * + * - Para que un dato de entrada sea correcto debe poseer un símbolo "°" + * y su unidad ("C" o "F"). + * - En caso contrario retornará un error. + */ + +/** + * + * @param {String} grados + */ +const conversorTemperatura = ( grados ) => { + + const reglaRegex = /^-?\d+(\.\d+)?\s*°\s*[cCfF]$/; + + if (!reglaRegex.test(grados)) { + return "Error en el formato" + } + + const numGrado = grados.split('').map((g) => { + return !isNaN(Number(g)) ? g : null + }).join(''); + + const condicion = grados.split('').filter((letra) => letra === "C" || letra === "F" ).join(''); + + if (condicion === "C") { + + return `${numGrado * (9 / 5) + 32} °F`; + + } else if ( condicion === "F" ){ + + return `${(numGrado - 32 ) * (5 / 9)} °C`; + + } else { + return "Error en la letra" + } +} + +// Pruebas +console.log(conversorTemperatura("25 °C")); // 77.00 °F +console.log(conversorTemperatura("77 °F")); // 25.00 °C +console.log(conversorTemperatura("abc °C")); // Error en el formato \ No newline at end of file diff --git a/soluciones-javascript/44-truco-o-trato/index.js b/soluciones-javascript/44-truco-o-trato/index.js new file mode 100644 index 000000000..902ac8e88 --- /dev/null +++ b/soluciones-javascript/44-truco-o-trato/index.js @@ -0,0 +1,99 @@ +/* + * Este es un reto especial por Halloween. + * Deberemos crear un programa al que le indiquemos si queremos realizar "Truco + * o Trato" y un listado (array) de personas con las siguientes propiedades: + * - Nombre de la niña o niño + * - Edad + * - Altura en centímetros + * + * Si las personas han pedido truco, el programa retornará sustos (aleatorios) + * siguiendo estos criterios: + * - Un susto por cada 2 letras del nombre por persona + * - Dos sustos por cada edad que sea un número par + * - Tres sustos por cada 100 cm de altura entre todas las personas + * - Sustos: 🎃 👻 💀 🕷 🕸 🦇 + * + * Si las personas han pedido trato, el programa retornará dulces (aleatorios) + * siguiendo estos criterios: + * - Un dulce por cada letra de nombre + * - Un dulce por cada 3 años cumplidos hasta un máximo de 10 años por persona + * - Dos dulces por cada 50 cm de altura hasta un máximo de 150 cm por persona + * - Dulces: 🍰 🍬 🍡 🍭 🍪 🍫 🧁 🍩 + * - En caso contrario retornará un error. + */ + +const trucoOTrato = (decision, arrayDePersonas) => { + const sustos = ["🎃", "👻", "💀", "🕷", "🕸", "🦇"]; + const dulces = ["🍰", "🍬", "🍡", "🍭", "🍪", "🍫", "🧁", "🍩"]; + const resultado = []; + + if (decision === "Truco") { + let sumaEdades = 0; + + arrayDePersonas.forEach((element) => { + const [nombre, edad, centimetro] = element; + + // Un susto por cada 2 letras del nombre por persona + if (nombre.length % 2 === 0) { + for (let i = 0; i < nombre.length / 2; i++) { + resultado.push(sustos[Math.floor(Math.random() * 6)]); + } + } else { + for (let i = 0; i < (nombre.length - 1) / 2; i++) { + resultado.push(sustos[Math.floor(Math.random() * 6)]); + } + } + + // Dos sustos por cada edad que sea un número par + if (edad % 2 === 0) { + for (let i = 0; i < 2; i++) { + resultado.push(sustos[Math.floor(Math.random() * 6)]); + } + } + + sumaEdades += centimetro; + }); + + // Tres sustos por cada 100 cm de altura entre todas las personas + for (let i = 100; i <= sumaEdades; i += 100) { + for (let j = 0; j < 3; j++) { + resultado.push(sustos[Math.floor(Math.random() * 6)]); + } + } + } else if (decision === "Trato") { + arrayDePersonas.forEach((element) => { + const [nombre, edad, centimetro] = element; + + // Un dulce por cada letra de nombre + for (let i = 0; i < nombre.length; i++) { + resultado.push(dulces[Math.floor(Math.random() * 8)]); + } + + // Un dulce por cada 3 años cumplidos hasta un máximo de 10 años por persona + for (let j = 0; j < edad; j += 3) { + resultado.push(dulces[Math.floor(Math.random() * 8)]); + } + + // Dos dulces por cada 50 cm de altura hasta un máximo de 150 cm por persona + for (let y = 0; y < 150; y += 50) { + if ( y > centimetro ) return resultado; + resultado.push(dulces[Math.floor(Math.random() * 8)]); + } + + }); + } else { + return "Error"; + } + + return resultado.join(" "); +}; + +const personas = [ + ["Juan", 10, 100], + ["Pablo", 8, 120], + ["Carla", 7, 80], + ["Lina", 9, 110], +]; + +console.log("Truco" + trucoOTrato("Truco", personas) + "\n"); +console.log("Trato" + trucoOTrato("Trato", personas) + "\n"); diff --git a/soluciones-javascript/45-bumeranes/index.js b/soluciones-javascript/45-bumeranes/index.js new file mode 100644 index 000000000..e4b24450c --- /dev/null +++ b/soluciones-javascript/45-bumeranes/index.js @@ -0,0 +1,27 @@ +/* + * Crea una función que retorne el número total de bumeranes de + * un array de números enteros e imprima cada uno de ellos. + * - Un bumerán (búmeran, boomerang) es una secuencia formada por 3 números + * seguidos, en el que el primero y el último son iguales, y el segundo + * es diferente. Por ejemplo [2, 1, 2]. + * - En el array [2, 1, 2, 3, 3, 4, 2, 4] hay 2 bumeranes ([2, 1, 2] + * y [4, 2, 4]). + */ + +const countBoomerangs = (arrayBoomerangs) => { + if (arrayBoomerangs.length < 3) return "El array no tiene suficientes elementos."; + + const boomerangs = []; + arrayBoomerangs.forEach((element, index, array) => { + if ( element === array[index + 2] && element !== array[index + 1] ) { + boomerangs.push([array[index], array[index + 1], array[index + 2]]); + } + }); + return `El array tiene ${boomerangs.length} \n **${boomerangs.join('**')}**`; +} + +console.log(countBoomerangs([2, 1, 2, 3, 3, 4, 2, 4])); +console.log(countBoomerangs([3, 1, 2, 1, 3, 4, 3, 4])); +console.log(countBoomerangs([9, 1, 9, 3, 4, 3, 2, 4])); +console.log(countBoomerangs([2, 2, 2])); // 0 (caso incorrecto corregido) +console.log(countBoomerangs([1, 2])); // 0 (array con menos de 3 elementos) \ No newline at end of file diff --git a/soluciones-javascript/46-contenedor-de-agua/index.js b/soluciones-javascript/46-contenedor-de-agua/index.js new file mode 100644 index 000000000..eba0a44d7 --- /dev/null +++ b/soluciones-javascript/46-contenedor-de-agua/index.js @@ -0,0 +1,55 @@ +/* + * Dado un array de números enteros positivos, donde cada uno + * representa unidades de bloques apilados, debemos calcular cuantas unidades + * de agua quedarán atrapadas entre ellos. + * + * - Ejemplo: Dado el array [4, 0, 3, 6, 1, 3]. + * + * ⏹ + * ⏹ + * ⏹💧💧 ⏹ + * ⏹💧⏹⏹💧 ⏹ + * ⏹💧⏹⏹💧 ⏹ + * ⏹💧⏹⏹⏹ ⏹ + * + * Representando bloque con ⏹︎ y agua con 💧, quedarán atrapadas 7 unidades + * de agua. Suponemos que existe un suelo impermeable en la parte inferior + * que retiene el agua. + */ + +const contenedorDeAgua = (array) => { + if (array.length < 3) return 0; // Si hay menos de 3 bloques, no puede atraparse agua + + const n = array.length; + let aguaAtrapada = 0; + + // Arrays auxiliares para almacenar el máximo a la izquierda y a la derecha + let maxIzq = new Array(n).fill(0); + let maxDer = new Array(n).fill(0); + + // Rellenar maxIzq + maxIzq[0] = array[0]; + for (let i = 1; i < n; i++) { + maxIzq[i] = Math.max(maxIzq[i - 1], array[i]); + } + + // Rellenar maxDer + maxDer[n - 1] = array[n - 1]; + for (let i = n - 2; i >= 0; i--) { + maxDer[i] = Math.max(maxDer[i + 1], array[i]); + } + + // Calcular el agua atrapada en cada posición + for (let i = 0; i < n; i++) { + aguaAtrapada += Math.max(0, Math.min(maxIzq[i], maxDer[i]) - array[i]); + } + + return aguaAtrapada; +}; + +// Ejemplo de uso +console.log(contenedorDeAgua([4, 0, 3, 6, 1, 3])); // Output: 7 +console.log(contenedorDeAgua([4, 0, 3, 6])); +console.log(contenedorDeAgua([5, 4, 3, 2, 1, 0])); +console.log(contenedorDeAgua([0, 1, 2, 3, 4, 5])); +console.log(contenedorDeAgua([4, 0, 3, 6, 1, 3, 0, 1, 6])); diff --git a/soluciones-javascript/47-donde-esta-el-robot/index.js b/soluciones-javascript/47-donde-esta-el-robot/index.js new file mode 100644 index 000000000..3dbfb834f --- /dev/null +++ b/soluciones-javascript/47-donde-esta-el-robot/index.js @@ -0,0 +1,58 @@ +/* + * Calcula dónde estará un robot (sus coordenadas finales) que se + * encuentra en una cuadrícula representada por los ejes "x" e "y". + * - El robot comienza en la coordenada (0, 0). + * - Para idicarle que se mueva, le enviamos un array formado por enteros + * (positivos o negativos) que indican la secuencia de pasos a dar. + * - Por ejemplo: [10, 5, -2] indica que primero se mueve 10 pasos, se detiene, + * luego 5, se detiene, y finalmente 2. + * El resultado en este caso sería (x: -5, y: 12) + * - Si el número de pasos es negativo, se desplazaría en sentido contrario al + * que está mirando. + * - Los primeros pasos los hace en el eje "y". Interpretamos que está mirando + * hacia la parte positiva del eje "y". + * - El robot tiene un fallo en su programación: cada vez que finaliza una + * secuencia de pasos gira 90 grados en el sentido contrario a las agujas + * del reloj. + */ + +/** + * + * @param {Array} secuenciaDePasos + */ +const dondeEstaElRobot = ( secuenciaDePasos ) => { + + const coordenadas = { x: 0, y: 0 }; + const direcciones = ['y+', 'x-', 'y-', 'x+']; + + for (let i = 0; i < secuenciaDePasos.length; i++) { + + let direccionActual = direcciones[ i % 4 ]; + let pasos = secuenciaDePasos[i]; + + if(pasos < 0){ + pasos = Math.abs(pasos); + switch (direccionActual) { + case 'y+': direccionActual = 'y-'; break; + case 'x-': direccionActual = 'x+'; break; + case 'y-': direccionActual = 'y+'; break; + case 'x+': direccionActual = 'x-'; break; + } + } + + switch (direccionActual) { + case 'y+': coordenadas.y += pasos; break; + case 'x-': coordenadas.x -= pasos; break; + case 'y-': coordenadas.y -= pasos; break; + case 'x+': coordenadas.x += pasos; break; + } + + } + + return coordenadas; + +} + +console.log(dondeEstaElRobot([10, 5, -2])); +console.log(dondeEstaElRobot([-10, -5, 2])); +console.log(dondeEstaElRobot([-10, -5, 4])); \ No newline at end of file diff --git a/soluciones-javascript/48-vocal-mas-comun/index.js b/soluciones-javascript/48-vocal-mas-comun/index.js new file mode 100644 index 000000000..9880ae4f1 --- /dev/null +++ b/soluciones-javascript/48-vocal-mas-comun/index.js @@ -0,0 +1,33 @@ +/* + * Crea un función que reciba un texto y retorne la vocal que + * más veces se repita. + * - Ten cuidado con algunos casos especiales. + * - Si no hay vocales podrá devolver vacío. + */ + +/** + * + * @param {String} string + */ +const vocalMasComun = (string) => { + + const vocales = string.toLowerCase().match(/[aeiou]/g); + if (!vocales) return ''; // Retorna vacío si no hay vocales + + return ( + "La letra que más se repite es: " + + string.split("") + .filter( + (word) => + word === "a" || word === "e" || word === "i" || word === "o" || word === "u" + ) + .reduce((acc, letter) => { + acc[letter] = (acc[letter] || 0) + 1; + return acc; + }) + ); +}; + +console.log(vocalMasComun("Hola yo soy el que no se repite no no no")); // o +console.log(vocalMasComun("ees es la letraee mas reeepeteee")); // e +console.log(vocalMasComun("xyz")); // "" \ No newline at end of file diff --git a/soluciones-javascript/49-calendario-adviento-2022/index.js b/soluciones-javascript/49-calendario-adviento-2022/index.js new file mode 100644 index 000000000..531537ba1 --- /dev/null +++ b/soluciones-javascript/49-calendario-adviento-2022/index.js @@ -0,0 +1,87 @@ +/* + * ¿Conoces el calendario de adviento de la comunidad (https://adviento.dev)? + * 24 días, 24 regalos sorpresa relacionados con desarrollo de software, + * ciencia y tecnología desde el 1 de diciembre. + * + * Enunciado: Crea una función que reciba un objeto de tipo "Date" y retorne + * lo siguiente: + * - Si la fecha coincide con el calendario de aDEViento 2022: Retornará el regalo + * de ese día (a tu elección) y cuánto queda para que finalice el sorteo de ese día. + * - Si la fecha es anterior: Cuánto queda para que comience el calendario. + * - Si la fecha es posterior: Cuánto tiempo ha pasado desde que ha finalizado. + * + * Notas: + * - Tenemos en cuenta que cada día del calendario comienza a medianoche 00:00:00 + * y finaliza a las 23:59:59. + * - Debemos trabajar con fechas que tengan año, mes, día, horas, minutos + * y segundos. + */ + +const regalos = [ + "📚 Guía rápida de Git y GitHub", + "💻 Snippet de código para autenticación JWT en Node.js", + "⌨️ Atajo de teclado para VS Code que te cambiará la vida", + "🎨 Mini curso de Flexbox y CSS Grid en 30 minutos", + "🔍 Cheat sheet de expresiones regulares (regex)", + "🖼️ Plantilla HTML + Tailwind para un portfolio web", + "🧼 Consejo sobre Clean Code: Nombra mejor tus variables", + "🐍 Script en Python para automatizar tareas repetitivas", + "🗃️ Truco para optimizar consultas en bases de datos SQL", + "🖱️ Atajo en la terminal para agilizar tu flujo de trabajo", + "🌐 Snippet de código para consumir APIs REST con Fetch", + "🛠️ Herramienta para generar datos ficticios para pruebas", + "🧩 Extensión de VS Code imprescindible para desarrolladores", + "⚛️ Cómo mejorar el rendimiento de tu app React", + "🎧 Lista de podcasts de tecnología y programación", + "🐳 Introducción a Docker con un ejemplo práctico", + "🔐 Explicación sencilla de OAuth y por qué deberías usarlo", + "📖 Top 5 libros recomendados sobre desarrollo web", + "🚀 Snippet para crear un servidor Express en 2 minutos", + "📝 Curso gratuito de JavaScript avanzado", + "🎨 Atajos de Figma para diseñadores y devs", + "🛡️ Plugin de Chrome para mejorar tu productividad", + "🤝 Guía para contribuir a proyectos Open Source", + "📄 Template para tu README en GitHub" +]; + +/** + * + * @param {Date} date + */ +const calendarioAdviento2022 = ( date ) => { + + const fechaInicio = new Date(2022, 11, 1, 0, 0, 0).getTime(); + const fechaFin = new Date(2022, 11, 24, 23, 59, 59).getTime(); + const dateInputInMiliseconds = date.getTime(); + + + if( dateInputInMiliseconds >= fechaInicio && dateInputInMiliseconds <= fechaFin ){ + const dia = date.getDate(); + const diaFinal = new Date(2022, 11, dia, 23, 59, 59).getTime(); + const diferencia = diaFinal - dateInputInMiliseconds; + const horasRestantes = Math.floor( diferencia / (1000 * 60 * 60 )); + const minutosRestantes = Math.floor( diferencia / (1000 * 60 )) / ( 1000 * 60 ); + + return `Regalo del día ${dia}: ${regalos[dia - 1]}. Quedan ${horasRestantes} horas y ${minutosRestantes} minutos para que termine el sorteo de hoy.`; + + } + + if (dateInputInMiliseconds < fechaInicio) { + const diferenciaInicio = fechaInicio - dateInputInMiliseconds; // Diferencia en milisegundos entre ahora y el inicio del calendario + const diasRestantes = Math.ceil(diferenciaInicio / (1000 * 60 * 60 * 24)); // Convertir la diferencia a días + + return `El calendario aún no ha comenzado. Faltan ${diasRestantes} días para el 1 de diciembre.`; + } + + if (dateInputInMiliseconds > fechaFin) { + const diferenciaFinal = dateInputInMiliseconds - fechaFin; // Diferencia en milisegundos entre ahora y el fin del calendario + const diasPasados = Math.floor(diferenciaFinal / (1000 * 60 * 60 * 24)); // Convertir la diferencia a días + + return `El calendario ya ha finalizado. Han pasado ${diasPasados} días desde el 24 de diciembre.`; + } + +} + +console.log(calendarioAdviento2022(new Date(2022, 11, 14, 12, 6, 12))); // Prueba con una fecha en diciembre +console.log(calendarioAdviento2022(new Date(2022, 10, 30))); // Prueba con una fecha antes del 1 de diciembre +console.log(calendarioAdviento2022(new Date(2022, 11, 25))); // Prueba con una fecha después del 24 de diciembre \ No newline at end of file diff --git a/soluciones-javascript/50-el-detector-de-handles/index.js b/soluciones-javascript/50-el-detector-de-handles/index.js new file mode 100644 index 000000000..d45f0d77d --- /dev/null +++ b/soluciones-javascript/50-el-detector-de-handles/index.js @@ -0,0 +1,26 @@ +/* + * Crea una función que sea capaz de detectar y retornar todos los + * handles de un texto usando solamente Expresiones Regulares. + * Debes crear una expresión regular para cada caso: + * - Handle usuario: Los que comienzan por "@" + * - Handle hashtag: Los que comienzan por "#" + * - Handle web: Los que comienzan por "www.", "http://", "https://" + * y finalizan con un dominio (.com, .es...) + */ + +const elDetectorDeHandles = ( texto ) => { + + const handleUser = texto.match((/@\w+/g)) || [] ; + const handleHashtag = texto.match((/#\w+/g)) || []; + const handleWeb = texto.match(/https?:\/\/[\w\-\.]+\.\w{2,}|www\.[\w\-\.]+\.\w{2,}/) || []; + + return { + handleUser, + handleHashtag, + handleWeb, + } + +} + +const texto = "Hola @usuario, visita https://openai.com o www.ejemplo.com. #programacion #regex"; +console.log(elDetectorDeHandles(texto)); \ No newline at end of file diff --git a/soluciones-javascript/51-la-encriptacion-de-karaca/index.js b/soluciones-javascript/51-la-encriptacion-de-karaca/index.js new file mode 100644 index 000000000..b2c69f229 --- /dev/null +++ b/soluciones-javascript/51-la-encriptacion-de-karaca/index.js @@ -0,0 +1,63 @@ +/* + * Crea una función que sea capaz de encriptar y desencriptar texto + * utilizando el algoritmo de encriptación de Karaca + * (debes buscar información sobre él). + */ + + +/** + * Algoritmo de encriptación de karaca + * @param {String} string + */ +const encriptarTexto = ( string ) => { + + const convencionVocales = { + a: 0, + e: 1, + i: 2, + o: 3, + u: 4, + }; + + const reverseString = string.split('').reverse().map((element) => { + for (let i = 0; i < Object.keys(convencionVocales).length; i++) { + if( element === Object.keys(convencionVocales)[i]){ + return Object.values(convencionVocales)[i]; + } + } + return element; + }).join(''); + + return reverseString + "aca"; + +} + +/** + * Algoritmo de desencriptación de karaca + * @param {String} stringEncriptado + */ +const desencriptarTexto = (stringEncriptado) => { + const convencionVocales = { + a: 0, + e: 1, + i: 2, + o: 3, + u: 4, + }; + + const stringWithoutAca = stringEncriptado.replace('aca', ''); + + return stringWithoutAca.split('').map((element) => { + for (let i = 0; i < Object.keys(convencionVocales).length; i++) { + if( Number(element) === Object.values(convencionVocales)[i]){ + return Object.keys(convencionVocales)[i]; + } + } + return element; + }).reverse().join(''); + +} + +const textoEncriptado = encriptarTexto('apple'); +console.log("Texto encriptado: " + textoEncriptado); +console.log("Texto desencriptado: " + desencriptarTexto(textoEncriptado)); \ No newline at end of file diff --git a/soluciones-javascript/52-el-reto-random/index.js b/soluciones-javascript/52-el-reto-random/index.js new file mode 100644 index 000000000..1331d6ea6 --- /dev/null +++ b/soluciones-javascript/52-el-reto-random/index.js @@ -0,0 +1,34 @@ +/* + * Crea tu propio enunciado para que forme parte de los retos de 2023. + * - Ten en cuenta que su dificultad debe ser asumible por la comunidad y seguir + * un estilosemejante a los que hemos realizado durante el año. + * - Si quieres también puedes proponer tu propia solución al reto + * (en el lenguaje que quieras). + */ + +/* + * Enunciado: Escribe un programa que reciba una cadena de texto y devuelva las palabras únicas que contiene, + * ignorando mayúsculas, minúsculas y signos de puntuación. Además, muestra cuántas veces aparece cada palabra repetida. + * Condiciones: + * - El programa debe ignorar signos de puntuación como , . ; : ! ?. + * - No debe diferenciar entre mayúsculas y minúsculas (Hola y hola cuentan como la misma palabra). + * - Devuelve un listado de palabras ordenado alfabéticamente junto con su frecuencia. + */ + +function contarPalabras(texto) { + // Quitar signos de puntuación y convertir a minúsculas + const limpio = texto.replace(/[.,;:!?\(\)]/g, "").toLowerCase(); + const palabras = limpio.split(/\s+/); + + const contador = {}; + palabras.forEach((palabra) => { + contador[palabra] = (contador[palabra] || 0) + 1; + }); + + const ordenado = Object.keys(contador).sort(); + ordenado.forEach((palabra) => { + console.log(`${palabra}: ${contador[palabra]}`); + }); +} + +contarPalabras("Hola mundo! Hola a todos en este hermoso mundo."); diff --git a/soluciones-javascript/53-fizz-buzz-v2/index.js b/soluciones-javascript/53-fizz-buzz-v2/index.js new file mode 100644 index 000000000..74c9fb1e4 --- /dev/null +++ b/soluciones-javascript/53-fizz-buzz-v2/index.js @@ -0,0 +1,24 @@ +/* + * Escribe un programa que muestre por consola (con un print) los + * números de 1 a 100 (ambos incluidos y con un salto de línea entre + * cada impresión), sustituyendo los siguientes: + * - Múltiplos de 3 por la palabra "fizz". + * - Múltiplos de 5 por la palabra "buzz". + * - Múltiplos de 3 y de 5 a la vez por la palabra "fizzbuzz". + */ + +const fizzBuzz = () => { + for (let i = 1; i <= 100; i++) { + if( i % 3 === 0 && i % 5 === 0){ + console.log("fizzbuzz"); + } else if( i % 3 === 0){ + console.log("fizz"); + } else if( i % 5 === 0 ){ + console.log("buzz"); + } else { + console.log(i); + } + } +} + +fizzBuzz(); \ No newline at end of file diff --git a/soluciones-javascript/54-el-lenguaje-hacker/index.js b/soluciones-javascript/54-el-lenguaje-hacker/index.js new file mode 100644 index 000000000..25ca7e74d --- /dev/null +++ b/soluciones-javascript/54-el-lenguaje-hacker/index.js @@ -0,0 +1,55 @@ +/* + * Escribe un programa que reciba un texto y transforme lenguaje natural a + * "lenguaje hacker" (conocido realmente como "leet" o "1337"). Este lenguaje + * se caracteriza por sustituir caracteres alfanuméricos. + * - Utiliza esta tabla (https://www.gamehouse.com/blog/leet-speak-cheat-sheet) + * con el alfabeto y los números en "leet". + * (Usa la primera opción de cada transformación. Por ejemplo "4" para la "a") + */ + +const leetTable = { + a: "4", + b: "8", + c: "(", + d: "|)", + e: "3", + f: "|=", + g: "6", + h: "#", + i: "1", + j: "_|", + k: "|<", + l: "1", + m: "|\\/|", + n: "|\\|", + o: "0", + p: "|*", + q: "0_", + r: "|2", + s: "5", + t: "7", + u: "|_|", + v: "\\/", + w: "\\/\\/", + x: "><", + y: "`/", + z: "2", +}; + +/** + * + * @param {String} sentence + */ +const convertirTextoALenguajeHacker = (sentence) => { + + return sentence.split('').map((char) => { + const lowerChar = char.toLowerCase(); + if(leetTable[lowerChar]){ + return char === lowerChar ? leetTable[lowerChar] : leetTable[lowerChar].toUpperCase(); + } + return char; + }).join(''); + +}; + +console.log(convertirTextoALenguajeHacker("Hacker")); \ No newline at end of file diff --git a/soluciones-javascript/55-el-partido-de-tenis/index.js b/soluciones-javascript/55-el-partido-de-tenis/index.js new file mode 100644 index 000000000..27c6d45a6 --- /dev/null +++ b/soluciones-javascript/55-el-partido-de-tenis/index.js @@ -0,0 +1,56 @@ +/* + * Escribe un programa que muestre cómo transcurre un juego de tenis y quién lo ha ganado. + * El programa recibirá una secuencia formada por "P1" (Player 1) o "P2" (Player 2), según quien + * gane cada punto del juego. + * + * - Las puntuaciones de un juego son "Love" (cero), 15, 30, 40, "Deuce" (empate), ventaja. + * - Ante la secuencia [P1, P1, P2, P2, P1, P2, P1, P1], el programa mostraría lo siguiente: + * 15 - Love + * 30 - Love + * 30 - 15 + * 30 - 30 + * 40 - 30 + * Deuce + * Ventaja P1 + * Ha ganado el P1 + * - Si quieres, puedes controlar errores en la entrada de datos. + * - Consulta las reglas del juego si tienes dudas sobre el sistema de puntos. + */ + +const elPartidoDeTenis = (array) => { + const puntajes = ["Love", 15, 30, 40]; + let p1 = 0; + let p2 = 0; + let terminado = false; + + for (let i = 0; i < array.length && !terminado; i++) { + // Sumar el punto al jugador correspondiente + if (array[i] === "P1") p1++; + else if (array[i] === "P2") p2++; + else { + console.log("Entrada inválida"); + return; + } + + // Imprimir estado actual antes de sumar el siguiente punto + if (p1 >= 3 && p2 >= 3) { + if (p1 === p2) { + console.log("Deuce"); + } else if (p1 === p2 + 1) { + console.log("Ventaja P1"); + } else if (p2 === p1 + 1) { + console.log("Ventaja P2"); + } else if (p1 >= p2 + 2) { + console.log("Ha ganado el P1"); + terminado = true; + } else if (p2 >= p1 + 2) { + console.log("Ha ganado el P2"); + terminado = true; + } + } else { + console.log(`${puntajes[p1]} - ${puntajes[p2]}`); + } + } +}; + +elPartidoDeTenis(["P1", "P1", "P2", "P2", "P1", "P2", "P1", "P1"]); diff --git a/soluciones-javascript/56-el-generador-de-passwords/index.js b/soluciones-javascript/56-el-generador-de-passwords/index.js new file mode 100644 index 000000000..c6d4e3c35 --- /dev/null +++ b/soluciones-javascript/56-el-generador-de-passwords/index.js @@ -0,0 +1,53 @@ +/* + * Escribe un programa que sea capaz de generar contraseñas de forma aleatoria. + * Podrás configurar generar contraseñas con los siguientes parámetros: + * - Longitud: Entre 8 y 16. + * - Con o sin letras mayúsculas. + * - Con o sin números. + * - Con o sin símbolos. + * (Pudiendo combinar todos estos parámetros entre ellos) + */ + +/** + * + * @param {Object} parameters + */ +const passwordGenerator = ( parameters ) => { + + const numbers = [1,2,3,4,5,6,7,8,9,0]; + const symbolsRules = ["@", "$","#","&","%","+"]; + const alphabet = ["a", "b", "c", "d", "e", "f", "g","h","i","j","k","l","m","ñ","o","p","q","r","s","t","w","x","y","z"]; + + const { length, lowerOrUpperCase, includeNumbers, includeSymbols } = parameters; + + if ( length < 8 || length > 16 ) { + return "Error, la longitud debe estar entre 8 y 16" + } + + let characters = alphabet; + + if( lowerOrUpperCase ){ + characters = characters.concat(alphabet.map(c => c.toUpperCase())) + } + + if ( includeNumbers ) { + characters = characters.concat(numbers); + } + + if ( includeSymbols ) { + characters = characters.concat( symbolsRules ); + } + + let password = ''; + + for (let i = 0; i < length; i++) { + const randomIndex = Math.floor(Math.random() * characters.length); + password += characters[randomIndex] + } + + return "Password: " + password; + +} + +// Ejemplo de uso +console.log(passwordGenerator({ length: 16, lowerOrUpperCase: true, includeNumbers: true, includeSymbols: true })); \ No newline at end of file diff --git a/soluciones-javascript/57-primo-fibonacci-y-par/index.js b/soluciones-javascript/57-primo-fibonacci-y-par/index.js new file mode 100644 index 000000000..9e3397803 --- /dev/null +++ b/soluciones-javascript/57-primo-fibonacci-y-par/index.js @@ -0,0 +1,43 @@ +/* + * Escribe un programa que, dado un número, compruebe y muestre si es primo, + * fibonacci y par. + * Ejemplos: + * - Con el número 2, nos dirá: "2 es primo, fibonacci y es par" + * - Con el número 7, nos dirá: "7 es primo, no es fibonacci y es impar" + */ + +function esPrimo(num) { + if (num < 2) return false; + for (let i = 2; i <= Math.sqrt(num); i++) { + if (num % i === 0) return false; + } + return true; +} + +function esFibonacci(num) { + let a = 0, b = 1, temp; + while (b < num) { + temp = a + b; + a = b; + b = temp; + } + return b === num || num === 0; +} + +function esPar(num) { + return num % 2 === 0; +} + +function analizarNumero(num) { + let resultado = `${num} `; + resultado += esPrimo(num) ? "es primo, " : "no es primo, "; + resultado += esFibonacci(num) ? "fibonacci y " : "no es fibonacci y "; + resultado += esPar(num) ? "es par." : "es impar."; + return resultado; +} + +console.log(analizarNumero(2)); +console.log(analizarNumero(7)); +console.log(analizarNumero(8)); +console.log(analizarNumero(13)); +console.log(analizarNumero(21)); \ No newline at end of file diff --git a/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.c b/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.c new file mode 100644 index 000000000..d4e961d12 --- /dev/null +++ b/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.c @@ -0,0 +1,5 @@ +#include +int main() { + printf("¡Hola Mundo!\n"); + return 0; +} \ No newline at end of file diff --git a/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.cpp b/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.cpp new file mode 100644 index 000000000..a890f81eb --- /dev/null +++ b/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.cpp @@ -0,0 +1,5 @@ +#include +int main() { + std::cout << "¡Hola Mundo!" << std::endl; + return 0; +} \ No newline at end of file diff --git a/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.java b/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.java new file mode 100644 index 000000000..97344a998 --- /dev/null +++ b/soluciones-javascript/58-hola-mundo-en-otros-lenguajes/holaMundo.java @@ -0,0 +1,6 @@ +public class HolaMundo { + public static void main(String[] args) { + System.out.println("¡Hola Mundo!"); + + } +} \ No newline at end of file diff --git a/soluciones-javascript/59-piedra-papel-tijera-lagarto-spock/index.js b/soluciones-javascript/59-piedra-papel-tijera-lagarto-spock/index.js new file mode 100644 index 000000000..8a6e7742e --- /dev/null +++ b/soluciones-javascript/59-piedra-papel-tijera-lagarto-spock/index.js @@ -0,0 +1,51 @@ +/* + * Crea un programa que calcule quien gana más partidas al piedra, + * papel, tijera, lagarto, spock. + * - El resultado puede ser: "Player 1", "Player 2", "Tie" (empate) + * - La función recibe un listado que contiene pares, representando cada jugada. + * - El par puede contener combinaciones de "🗿" (piedra), "📄" (papel), + * "✂️" (tijera), "🦎" (lagarto) o "🖖" (spock). + * - Ejemplo. Entrada: [("🗿","✂️"), ("✂️","🗿"), ("📄","✂️")]. Resultado: "Player 2". + * - Debes buscar información sobre cómo se juega con estas 5 posibilidades. + */ + +/** + * Función que calcula quien gana en un juego de piedra papel o tijera + * @param {Array} jugadas + */ +const piedraPapelTijeraLagartoSpock = ( jugadas ) => { + + let conteoPlayer1 = 0; + let conteoPlayer2 = 0; + + jugadas.forEach((jugada) => { + const [ player1, player2 ] = jugada; + + if(player1 === player2){ + return; + } + + if( (player1 === "🗿" && player2 === "✂️") || (player1 === "🗿" && player2 === "🦎") ){ + conteoPlayer1++; + } else if((player1 === "📄" && player2 === "🗿") || (player1 === "📄" && player2 === "🖖")){ + conteoPlayer1++; + } else if((player1 === "✂️" && player2 === "📄") || (player1 === "✂️" && player2 === "🦎")){ + conteoPlayer1++; + } else if((player1 === "🦎" && player2 === "📄") || (player1 === "🦎" && player2 === "🖖")){ + conteoPlayer1++; + } else if((player1 === "🖖" && player2 === "✂️") || (player1 === "🖖" && player2 === "🗿")){ + conteoPlayer1++; + } else { + conteoPlayer2++; + } + + }); + + + return conteoPlayer1 > conteoPlayer2 ? "Player 1" : conteoPlayer1 < conteoPlayer2 ? "Player 2" : "Tie"; + +} + +console.log(piedraPapelTijeraLagartoSpock([["🗿","✂️"], ["✂️","🗿"], ["📄","✂️"]])); // "Player 2" +console.log(piedraPapelTijeraLagartoSpock([["🦎","✂️"], ["✂️","📄"], ["🖖","✂️"]])); // "Player 1" +console.log(piedraPapelTijeraLagartoSpock([["🗿","✂️"], ["✂️","📄"], ["✂️","🖖"], ["🗿","📄"]])); // "Tie" \ No newline at end of file diff --git a/soluciones-javascript/60-el-sombrero-seleccionador/index.js b/soluciones-javascript/60-el-sombrero-seleccionador/index.js new file mode 100644 index 000000000..4b1896cdb --- /dev/null +++ b/soluciones-javascript/60-el-sombrero-seleccionador/index.js @@ -0,0 +1,97 @@ +/* + * Crea un programa que simule el comportamiento del sombrero selccionador del + * universo mágico de Harry Potter. + * - De ser posible realizará 5 preguntas (como mínimo) a través de la terminal. + * - Cada pregunta tendrá 4 respuestas posibles (también a selecciona una a través de terminal). + * - En función de las respuestas a las 5 preguntas deberás diseñar un algoritmo que + * coloque al alumno en una de las 4 casas de Hogwarts: + * (Gryffindor, Slytherin , Hufflepuff y Ravenclaw) + * - Ten en cuenta los rasgos de cada casa para hacer las preguntas + * y crear el algoritmo seleccionador: + * Por ejemplo, en Slytherin se premia la ambición y la astucia. + */ + +const readline = require("readline"); + +const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, +}); + +const preguntas = [ + { + pregunta: "¿Qué cualidad valoras más en una persona?", + opciones: ["Valentía", "Ambición", "Lealtad", "Inteligencia"], + puntos: { Gryffindor: 1, Slytherin: 2, Hufflepuff: 3, Ravenclaw: 4 }, + }, + { + pregunta: "¿Qué harías si ves a alguien haciendo trampa en un examen?", + opciones: [ + "Lo denuncio inmediatamente", + "Lo ignoro, no es mi problema", + "Ayudo a quien hizo trampa a mejorar", + "Intento razonar con la persona", + ], + puntos: { Gryffindor: 1, Slytherin: 2, Hufflepuff: 3, Ravenclaw: 4 }, + }, + { + pregunta: "¿Qué tipo de libros prefieres leer?", + opciones: ["Aventuras", "Estrategia", "Historias conmovedoras", "Ciencia"], + puntos: { Gryffindor: 1, Slytherin: 2, Hufflepuff: 3, Ravenclaw: 4 }, + }, + { + pregunta: "¿Cuál de estos lugares te atrae más?", + opciones: [ + "Un campo abierto y desafiante", + "Un castillo con muchos secretos", + "Un jardín acogedor", + "Una biblioteca infinita", + ], + puntos: { Gryffindor: 1, Slytherin: 2, Hufflepuff: 3, Ravenclaw: 4 }, + }, + { + pregunta: "Si tuvieras que enfrentar un desafío, ¿qué harías?", + opciones: [ + "Voy con determinación y sin miedo", + "Planeo cada paso meticulosamente", + "Busco apoyo en mis amigos", + "Investigo la mejor solución posible", + ], + puntos: { Gryffindor: 1, Slytherin: 2, Hufflepuff: 3, Ravenclaw: 4 }, + }, +]; + +let puntajes = { Gryffindor: 0, Slytherin: 0, Hufflepuff: 0, Ravenclaw: 0 }; +let preguntaActual = 0; + +const elSombreroSeleccionador = () => { + if (preguntaActual < preguntas.length) { + const { pregunta, opciones, puntos } = preguntas[preguntaActual]; + console.log(`\n${pregunta}`); + opciones.forEach((opcion, i) => console.log(`${i + 1}. ${opcion}`)); + rl.question("Elige una opción (1-4): ", (respuesta) => { + const eleccion = parseInt(respuesta); + if (eleccion >= 1 && eleccion <= 4) { + Object.keys(puntajes).forEach((casa) => { + if (puntos[casa] === eleccion) puntajes[casa]++; + }); + preguntaActual++; + elSombreroSeleccionador(); + } else { + console.log("Por favor, ingresa un número válido."); + elSombreroSeleccionador(); + } + }); + } else { + rl.close(); + asignarCasa(); + } +}; + +const asignarCasa = () => { + let casaAsignada = Object.keys(puntajes).reduce((a, b) => (puntajes[a] > puntajes[b] ? a : b)); + console.log(`\n¡Felicidades! Has sido asignado a ${casaAsignada} 🏰`); +}; +console.log("Bienvenido al Sombrero Seleccionador de Hogwarts 🎩✨"); + +elSombreroSeleccionador(); \ No newline at end of file diff --git a/soluciones-javascript/61-el-generador-pseudoaleatorio/index.js b/soluciones-javascript/61-el-generador-pseudoaleatorio/index.js new file mode 100644 index 000000000..ad757814a --- /dev/null +++ b/soluciones-javascript/61-el-generador-pseudoaleatorio/index.js @@ -0,0 +1,27 @@ +/* + * Crea un generador de números pseudoaleatorios entre 0 y 100. + * - No puedes usar ninguna función "random" (o semejante) del + * lenguaje de programación seleccionado. + * + * Es más complicado de lo que parece... + */ + +const generadorPseudoaleatorio = (seed) => { + + let current = seed; + const m = 101; // Módulo (define el rango 0-100) + const a = 31; // Multiplicador + const c = 7; // Incremento + + return function next() { + current = (a * current + c) % m; + return current; + }; + +} + +const random = generadorPseudoaleatorio(Date.now() % 101); + +console.log(random()); +console.log(random()); +console.log(random()); \ No newline at end of file diff --git a/soluciones-javascript/62-heterograma-isograma-pangrama/index.js b/soluciones-javascript/62-heterograma-isograma-pangrama/index.js new file mode 100644 index 000000000..d4d453aab --- /dev/null +++ b/soluciones-javascript/62-heterograma-isograma-pangrama/index.js @@ -0,0 +1,37 @@ +/* + * Crea 3 funciones, cada una encargada de detectar si una cadena de + * texto es un heterograma, un isograma o un pangrama. + * - Debes buscar la definición de cada uno de estos términos. + */ + +function esHeterograma(texto) { + const letras = new Set(); + for (let letra of texto.toLowerCase().replace(/[^a-záéíóúüñ]/g, "")) { + if (letras.has(letra)) return false; + letras.add(letra); + } + return true; +} + +function esIsograma(texto) { + const conteo = {}; + const letras = texto.toLowerCase().replace(/[^a-záéíóúüñ]/g, ""); + + for (let letra of letras) { + conteo[letra] = (conteo[letra] || 0) + 1; + } + + const valores = Object.values(conteo); + return valores.every(v => v === valores[0]); +} + +function esPangrama(texto) { + const alfabeto = new Set("abcdefghijklmnñopqrstuvwxyz"); + const letrasEnTexto = new Set(texto.toLowerCase().replace(/[^a-záéíóúüñ]/g, "")); + return [...alfabeto].every(letra => letrasEnTexto.has(letra)); +} + +// Ejemplos de uso +console.log(esHeterograma("murciélago")); +console.log(esIsograma("murciélago")); +console.log(esPangrama("El veloz murciélago hindú comía feliz cardillo y kiwi.")); \ No newline at end of file