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");