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