diff --git a/README.md b/README.md
index cc65befe06..fde3bb6659 100644
--- a/README.md
+++ b/README.md
@@ -34,9 +34,10 @@ Aquí encontrarás el listado de retos, su fecha de publicación, dificultad y e
* **#14** - 03/04/23 | Fácil | [`OCTAL Y HEXADECIMAL`](./Retos/Reto%20%2314%20-%20OCTAL%20Y%20HEXADECIMAL%20%5BFácil%5D/ejercicio.md) | Correcciones: [[EN VÍDEO](https://youtu.be/T8qY1nUCHkM)] [[MI SOLUCIÓN](./Retos/Reto%20%2314%20-%20OCTAL%20Y%20HEXADECIMAL%20%5BFácil%5D/python/mouredev.py)] [[COMUNIDAD](./Retos/Reto%20%2314%20-%20OCTAL%20Y%20HEXADECIMAL%20%5BFácil%5D/)]
* **#15** - 10/04/23 | Fácil | [`AUREBESH`](./Retos/Reto%20%2315%20-%20AUREBESH%20%5BFácil%5D/ejercicio.md) | Correcciones: [[MI SOLUCIÓN](./Retos/Reto%20%2315%20-%20AUREBESH%20%5BFácil%5D/python/mouredev.py)] [[COMUNIDAD](./Retos/Reto%20%2315%20-%20AUREBESH%20%5BFácil%5D/)]
* **#16** - 17/04/23 | Media | [`LA ESCALERA`](./Retos/Reto%20%2316%20-%20LA%20ESCALERA%20%5BMedia%5D/ejercicio.md) | Correcciones: [[MI SOLUCIÓN](./Retos/Reto%20%2316%20-%20LA%20ESCALERA%20%5BMedia%5D/python/mouredev.py)] [[COMUNIDAD](./Retos/Reto%20%2316%20-%20LA%20ESCALERA%20%5BMedia%5D/)]
-* **#17** - 24/04/23 | Difícil | [`GIT Y GITHUB`](./Retos/Reto%20%2317%20-%20GIT%20Y%20GITHUB%20%5BDifícil%5D/ejercicio.md) | Último reto publicado
+* **#17** - 24/04/23 | Difícil | [`GIT Y GITHUB`](./Retos/Reto%20%2317%20-%20GIT%20Y%20GITHUB%20%5BDifícil%5D/ejercicio.md) | Correcciones: [[MI SOLUCIÓN](./Retos/Reto%20%2317%20-%20GIT%20Y%20GITHUB%20%5BDifícil%5D/python/mouredev.py)] [[COMUNIDAD](./Retos/Reto%20%2317%20-%20GIT%20Y%20GITHUB%20%5BDifícil%5D/)]
+* **#18** - 01/05/23 | Difícil | [`WEB SCRAPING`](./Retos/Reto%20%2318%20-%20WEB%20SCRAPING%20%5BDifícil%5D/ejercicio.md) | Último reto publicado
-> **Corrección y Publicación próximo reto - 01/05/23 | [🗓️ Horario evento corrección en directo](https://discord.gg/mouredev?event=1100104369787109496) en [Twitch](https://twitch.tv/mouredev)**
+> **Corrección y Publicación próximo reto - 11/05/23 | [🗓️ Horario evento corrección en directo](https://discord.gg/mouredev?event=1102500650471936050) en [Twitch](https://twitch.tv/mouredev)**
*Puedes ejecutar el archivo [language_stats.py](./Retos/language_stats.py) para visualizar las estadísticas de uso de cada lenguaje.*
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/c#/mchocho99.cs" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/c#/mchocho99.cs"
new file mode 100644
index 0000000000..99b63dccae
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/c#/mchocho99.cs"
@@ -0,0 +1,30 @@
+public static void reto0()
+{
+ /*
+ * 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".
+ */
+ for (int i = 0; i <= 100; i++)
+ {
+ string result = "";
+ if (i % 3 == 0)
+ {
+ result += "fizz";
+ }
+ if (i % 5 == 0)
+ {
+ result += "buzz";
+ }
+ if (result.Equals(""))
+ {
+ Console.WriteLine(i);
+ } else
+ {
+ Console.WriteLine(result);
+ }
+ }
+}
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/aaizaguirre.js" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/aaizaguirre.js"
new file mode 100644
index 0000000000..cdc5b29e1f
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/aaizaguirre.js"
@@ -0,0 +1,14 @@
+for (let i = 1; i <= 100; i++){
+ if (i % 15 === 0){
+ console.log("fizzbuzz");
+ continue;
+ } if (i % 3 === 0){
+ console.log("fizz");
+ continue;
+ } if (i % 5 === 0){
+ console.log("buzz");
+ continue;
+ } else{
+ console.log(i)
+ };
+};
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/guido2288.js" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/guido2288.js"
new file mode 100644
index 0000000000..68d7651b37
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/guido2288.js"
@@ -0,0 +1,13 @@
+for (let i = 1; i <= 100; i++) {
+
+ if (i % 3 === 0 && i % 5 === 0) {
+ console.log('fizzbuzz' + '\n')
+ } else if (i % 3 === 0 && i % 5 != 0) {
+ console.log('fizz' + '\n')
+ } else if (i % 3 != 0 && i % 5 === 0) {
+ console.log('buzz' + '\n')
+ } else {
+ console.log(i + '\n')
+ }
+
+}
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/mchocho99.js" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/mchocho99.js"
new file mode 100644
index 0000000000..bb669ea73d
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/javascript/mchocho99.js"
@@ -0,0 +1,24 @@
+export const reto0 = () => {
+ /*
+ * 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".
+ */
+ for (let i = 1; i <= 100; i++) {
+ let result = "";
+ if (i % 3 === 0) {
+ result += "fizz";
+ }
+ if (i % 5 === 0) {
+ result += "buzz";
+ }
+ if (result) {
+ console.log(result)
+ } else {
+ console.log(i);
+ }
+ }
+}
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/php/josea2r.php" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/php/josea2r.php"
new file mode 100644
index 0000000000..2a479f9286
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/php/josea2r.php"
@@ -0,0 +1,23 @@
+/*
+ * 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".
+ */
+
+";
+ } else {
+ echo $return;
+ echo "
";
+ }
+ }
+}
+
+reto0();
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/Air94.py" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/Air94.py"
new file mode 100644
index 0000000000..74a5d8be33
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/Air94.py"
@@ -0,0 +1,15 @@
+
+def analyze(n):
+ if i%5 == 0 and i%3==0:
+ print("\nfizzbuzz")
+ elif i%5 == 0:
+ print("\nbuzz")
+ elif i%3==0:
+ print("\nfizz")
+ else:
+ print("\n", i)
+
+
+for i in range(1, 101):
+ analyze(i)
+
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/aaizaguirre.py" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/aaizaguirre.py"
new file mode 100644
index 0000000000..34b20c9501
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/aaizaguirre.py"
@@ -0,0 +1,9 @@
+for i in range(1,101):
+ if i % 15 == 0:
+ print("fizzbuzz")
+ elif i % 3 == 0:
+ print("fizz")
+ elif i % 5 == 0:
+ print("buzz")
+ else:
+ print(i)
\ No newline at end of file
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/akaidmaru.py" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/akaidmaru.py"
new file mode 100644
index 0000000000..58968fd224
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/akaidmaru.py"
@@ -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".
+'''
+
+
+def fizzbuzz():
+ for num in range(1, 101):
+ if num % 3 == 0 and num % 5 == 0:
+ print('FizzBuzz\n')
+ elif num % 3 == 0:
+ print('Fizz\n')
+ elif num % 5 == 0:
+ print('Buzz\n')
+ else:
+ print(f'{num}\n')
+
+
+if __name__ == "__main__":
+ fizzbuzz()
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/ignafuentes.py" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/ignafuentes.py"
new file mode 100644
index 0000000000..be718fc859
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/ignafuentes.py"
@@ -0,0 +1,20 @@
+## Enunciado
+
+# /*
+# * 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".
+# */
+
+for number in range(1, 101):
+ if number % 3 == 0 and number % 5 == 0:
+ print('fizzbuzz')
+ elif number % 3 == 0:
+ print('fizz')
+ elif number % 5 == 0:
+ print('buzz')
+ else:
+ print(number)
\ No newline at end of file
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/martin-aq.py" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/martin-aq.py"
new file mode 100644
index 0000000000..0484d598f4
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/martin-aq.py"
@@ -0,0 +1,11 @@
+def fizzbuzz():
+ for num in range(1,101):
+ if num % 3 == 0 and num % 5 == 0:
+ print("fizzbuzz")
+ elif num % 3 == 0:
+ print("fizz")
+ elif num % 5 == 0:
+ print("buzz")
+ else:
+ print(num)
+fizzbuzz()
\ No newline at end of file
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/saurivane.py" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/saurivane.py"
new file mode 100644
index 0000000000..f80a20cd8b
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/python/saurivane.py"
@@ -0,0 +1,23 @@
+"""""
+/*
+ * 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".
+ */
+"""
+
+def fizzbuzz(num):
+ if num%3 == 0 and num%5 == 0:
+ return "fizzbuzz"
+ elif num%3 == 0:
+ return "fizz"
+ elif num%5 == 0:
+ return "buzz"
+ else:
+ return num
+
+for i in range(1,101):
+ print(fizzbuzz(i))
\ No newline at end of file
diff --git "a/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/typescript/zerchito.ts" "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/typescript/zerchito.ts"
new file mode 100644
index 0000000000..f8991d5da1
--- /dev/null
+++ "b/Retos/Reto #0 - EL FAMOSO FIZZ BUZZ [F\303\241cil]/typescript/zerchito.ts"
@@ -0,0 +1,25 @@
+/*
+ * 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 MAX = 100;
+const MIN = 1;
+function fizzbuzz(): void {
+ for(let num = MIN; num<=MAX; num++){
+ let response = '';
+ if ( num%3 ===0 ) {
+ response = 'fizz';
+ }
+ if ( num%5 === 0 ) {
+ response = response + 'buzz';
+ }
+ console.log(response || num);
+ }
+}
+
+fizzbuzz();
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/java/mchocho99.java" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/java/mchocho99.java"
new file mode 100644
index 0000000000..5458b2c0c5
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/java/mchocho99.java"
@@ -0,0 +1,54 @@
+ private static final Map DICTIONARY = new HashMap<>() {{
+ put('A', "4");
+ put('B', "I3");
+ put('C', "[");
+ put('D', ")");
+ put('E', "3");
+ put('F', "|=");
+ put('G', "&");
+ put('H', "#");
+ put('I', "1");
+ put('J', ",_|");
+ put('K', ">|");
+ put('L', "£");
+ put('M', "/\\/\\");
+ put('N', "^/");
+ put('O', "0");
+ put('P', "|*");
+ put('Q', "(_,)");
+ put('R', "I2");
+ put('S', "5");
+ put('T', "7");
+ put('U', "(_)");
+ put('V', "\\/");
+ put('W', "\\/\\/");
+ put('X', "><");
+ put('Y', " j");
+ put('Z', "2");
+ put('0', "o");
+ put('1', "L");
+ put('2', "R");
+ put('3', "E");
+ put('4', "A");
+ put('5', "S");
+ put('6', "b");
+ put('7', "T");
+ put('8', "B");
+ put('9', "g");
+ put(' ', " ");
+ }};
+
+ public static void reto1 (String text) {
+ /*
+ * 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")
+ */
+ String upperText = text.toUpperCase();
+ for (int i = 0; i < upperText.length(); i++) {
+ System.out.print(DICTIONARY.get(upperText.charAt(i)));
+ }
+ }
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/javascript/guido2288.js" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/javascript/guido2288.js"
new file mode 100644
index 0000000000..5f626545af
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/javascript/guido2288.js"
@@ -0,0 +1,45 @@
+function leetLenguaje(word) {
+
+ const leetWord = word.toLowerCase()
+ .replaceAll('1', 'L')
+ .replaceAll('2', 'R')
+ .replaceAll('3', 'E')
+ .replaceAll('4', 'A')
+ .replaceAll('5', 'S')
+ .replaceAll('6', 'b')
+ .replaceAll('7', 'T')
+ .replaceAll('8', 'B')
+ .replaceAll('9', 'g')
+ .replaceAll('0', 'o')
+ .replaceAll('a', '4')
+ .replaceAll('b', 'I3')
+ .replaceAll('c', '[')
+ .replaceAll('d', ')')
+ .replaceAll('e', '3')
+ .replaceAll('f', '|=')
+ .replaceAll('g', '&')
+ .replaceAll('h', '#')
+ .replaceAll('i', '1')
+ .replaceAll('j', ',_|')
+ .replaceAll('k', '>|')
+ .replaceAll('l', '1')
+ .replaceAll('m', '/\\/\\')
+ .replaceAll('n', '^/')
+ .replaceAll('o', '0')
+ .replaceAll('p', '|*')
+ .replaceAll('q', '(_,)')
+ .replaceAll('r', 'I2')
+ .replaceAll('s', '5')
+ .replaceAll('t', '7')
+ .replaceAll('u', '(_)')
+ .replaceAll('v', '\/')
+ .replaceAll('w', '\/\/')
+ .replaceAll('x', '><')
+ .replaceAll('y', 'j')
+ .replaceAll('z', '2')
+
+ return leetWord;
+};
+
+console.log(leetLenguaje('Hello word!'))
+
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/MariusBD.py" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/MariusBD.py"
new file mode 100644
index 0000000000..48d719ea79
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/MariusBD.py"
@@ -0,0 +1,35 @@
+
+
+
+"""
+/*
+ * 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")
+ */
+"""
+
+def leet_translator(texto):
+ texto = texto.lower()
+ leet_dict = {
+ 'A':'4','B':'I3','C':'[','D':')','E':'3','F':'|=','G':'&','H':'#','I':'1','J':',_|','K':'>|','L':'1','M':'/\/\ ','N':'^/','O':'0',
+ 'P':'|*','Q':'(_,)','R':'I2','S':'5','T':'7','U':'(_)','V':'\/','W':'\/\/','X':'><',
+ 'Y':'j','Z':'2','0':'O','1':'I','2':'Z','3':'E','4':'A','5':'S','6':'b','7':'T','8':'B','9':'g'}
+ leet_traducido = ""
+
+ for letra in texto:
+ if letra == ' ':
+ leet_traducido += letra
+ for clave,valor in leet_dict.items():
+ if letra.lower() == clave.lower():
+ leet_traducido += valor
+
+ return(leet_traducido)
+
+print(leet_translator('El Lenguaje Hacker Del Programador'))
+
+
+
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/akaidmaru.py" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/akaidmaru.py"
new file mode 100644
index 0000000000..7a55fa3fbe
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/akaidmaru.py"
@@ -0,0 +1,51 @@
+'''
+* 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")
+'''
+
+leet_dir = {
+ 'a': '4',
+ 'b': 'I3',
+ 'c': '[',
+ 'd': ')',
+ 'e': '3',
+ 'f': '|=',
+ 'g': '&',
+ 'h': '#',
+ 'i': '1',
+ 'j': ',_|',
+ 'k': '>|',
+ 'l': '£',
+ 'm': '|\/|',
+ 'n': '^/',
+ 'o': '0',
+ 'p': '|*',
+ 'q': '(_,)',
+ 'r': 'I2',
+ 's': '5',
+ 't': '7',
+ 'u': '(_)',
+ 'v': '\/',
+ 'w': '\/\/',
+ 'x': '><',
+ 'y': 'j',
+ 'z': '2',
+}
+
+def lenguaje_hacker():
+ text = input('Please, input your Text to convert to l33t code:\n>').lower()
+ leet_text = ''
+
+ for letter in text:
+ if letter in leet_dir:
+ leet_text += leet_dir[letter]
+ else:
+ leet_text += letter
+ return print(leet_text)
+
+
+lenguaje_hacker()
\ No newline at end of file
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/ignafuentes.py" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/ignafuentes.py"
new file mode 100644
index 0000000000..da8889a3c7
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/ignafuentes.py"
@@ -0,0 +1,17 @@
+def traductor_hacker(texto):
+
+ lenguaje = {'a': '4', 'b': 'I3', 'c': '[', 'd': ')', 'e': '3', 'f': '|=', 'g': '&', 'h': '#', 'i': '1', 'j': ',_|', 'k': '>|', 'l': '1', 'm': 'JVI', 'n': '^/', 'o': '0', 'p': '|*', 'q': '(_,)', 'r': 'I2', 's': '5', 't': '7', 'u': '(_)', 'v': '\/', 'w': '\/\/', 'x': '><', 'y': 'j', 'z': '2' }
+
+ texto_traducido = ''
+
+ for caracter in texto:
+ if caracter.lower() in lenguaje.keys():
+ texto_traducido += lenguaje[caracter.lower()]
+ else:
+ texto_traducido += caracter
+
+ return texto_traducido
+
+
+print(traductor_hacker('Hola a todo el mundo!'))
+print(traductor_hacker(input('Ingresar el texto a traducir => ')))
\ No newline at end of file
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/martin-aq.py" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/martin-aq.py"
new file mode 100644
index 0000000000..95eceeba5b
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/martin-aq.py"
@@ -0,0 +1,21 @@
+def translate_to_leet(string):
+
+ leet_string = ""
+
+ hashMap = {
+ "a": "4", "b": "|3", "c": "[", "d": ")", "e": "3", "f": "|=", "g": "&", "h": "#",
+ "i": "1", "j": ",_|", "k": ">|", "l": "1", "m": "|V|","n": "^/", "o": "0", "p": "|*",
+ "q": "(_,)", "r": "|2", "s": "5", "t": "7", "u": "(_)", "v": "|/", "w": "VV",
+ "x": "><", "y": "j", "z": "2", "1": "L", "2": "R", "3": "E", "4": "A", "5": "S",
+ "6": "b", "7": "T", "8": "B", "9": "g", "0": "o"
+ }
+
+ for word in string.lower():
+ if word in hashMap.keys():
+ leet_string += hashMap[word]
+ else:
+ leet_string += word
+
+ return leet_string
+
+print(translate_to_leet(input("Ingrese una cadena de texto: ")))
\ No newline at end of file
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/saurivane.py" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/saurivane.py"
new file mode 100644
index 0000000000..b738823f22
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/python/saurivane.py"
@@ -0,0 +1,23 @@
+"""/*
+ * 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")
+ */
+ """
+
+letras=["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","1","2","3","4","5","6","7","8","9","0", " "]
+
+valores=["4","I3","[",")","3","|=","&","#","1",",_|",">|","1","/\/\\","^/","0","|*","(_,)","I2","5","7","(_)","\/","\/\/","><","j","2","L","R","E","A","S","b","T","B","g","o", " "]
+
+language_hacker = dict(zip(letras,valores))
+
+print("Introduzca el texto a convertir")
+convertir = input().lower()
+resultado = ""
+for letter in convertir:
+ resultado += language_hacker[letter]
+
+print("Su texto hackeado es " + resultado)
\ No newline at end of file
diff --git "a/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/typescript/zerchito.ts" "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/typescript/zerchito.ts"
new file mode 100644
index 0000000000..cef15a76e0
--- /dev/null
+++ "b/Retos/Reto #1 - EL LENGUAJE HACKER [F\303\241cil]/typescript/zerchito.ts"
@@ -0,0 +1,61 @@
+/*
+ * 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 HACKER_CODE = {
+ a: '4',
+ b: 'I3',
+ c: '[',
+ d: ')',
+ e: '3',
+ f: '|=',
+ g: '&',
+ h: '#',
+ i: '1',
+ j: ',_|',
+ k: '>|',
+ l: '1',
+ m: '/\\/\\',
+ n: '^/',
+ o: '0',
+ p: '|*',
+ q: '(_,)',
+ r: 'I2',
+ s: '5',
+ t: '7',
+ u: '(_)',
+ v: '\\/',
+ w: '\\/\\/',
+ x: '><',
+ y: 'j',
+ z: '2',
+ 1: 'L',
+ 2: 'R',
+ 3: 'E',
+ 4: 'A',
+ 5: 'S',
+ 6: 'b',
+ 7: 'T',
+ 8: 'B',
+ 9: 'g',
+ 0: 'o'
+};
+
+function transformNaturalToHacker(natural:string):string {
+ return natural
+ .toLowerCase()
+ .split('')
+ .map(character => HACKER_CODE[character] || character)
+ .join('')
+}
+
+const NATURAL = 'Lenguaje Natural (zerchito)';
+const HACKER = transformNaturalToHacker(NATURAL);
+
+console.log(`Natural: ${NATURAL}`);
+console.log(`Hacker: ${HACKER}`);
\ No newline at end of file
diff --git a/Retos/Reto #10 - LA API [Media]/javascript/EzeSandes.js b/Retos/Reto #10 - LA API [Media]/javascript/EzeSandes.js
new file mode 100644
index 0000000000..8d5d86a17a
--- /dev/null
+++ b/Retos/Reto #10 - LA API [Media]/javascript/EzeSandes.js
@@ -0,0 +1,30 @@
+/*
+ * Llamar a una API es una de las tareas más comunes en programación.
+ *
+ * Implementa una llamada HTTP a una API (la que tú quieras) y muestra su
+ * resultado a través de la terminal. Por ejemplo: Pokémon, Marvel...
+ *
+ * Aquí tienes un listado de posibles APIs:
+ * https://github.com/public-apis/public-apis
+ */
+
+const API_URL = 'https://v2.jokeapi.dev/joke/Programming';
+
+async function fetchData(url, options = undefined) {
+ try {
+ const res = await fetch(url, options);
+ if (!res.ok) throw new Error('⛔ERROR RESPONSE DATA⛔');
+
+ return await res.json();
+ } catch (error) {
+ console.log(error.message);
+ }
+}
+
+fetchData(API_URL)
+ .then(data => {
+ if (data.error) throw new Error('⛔DATA ERROR⛔');
+
+ console.log(data);
+ })
+ .catch(error => console.log(error.message));
diff --git a/Retos/Reto #10 - LA API [Media]/javascript/giovanyosorio.js b/Retos/Reto #10 - LA API [Media]/javascript/giovanyosorio.js
new file mode 100644
index 0000000000..204fcbe3b3
--- /dev/null
+++ b/Retos/Reto #10 - LA API [Media]/javascript/giovanyosorio.js
@@ -0,0 +1,22 @@
+/*
+ * Llamar a una API es una de las tareas más comunes en programación.
+ *
+ * Implementa una llamada HTTP a una API (la que tú quieras) y muestra su
+ * resultado a través de la terminal. Por ejemplo: Pokémon, Marvel...
+ *
+ * Aquí tienes un listado de posibles APIs:
+ * https://github.com/public-apis/public-apis
+ */
+
+//API CORONAVIRUS
+//https://coronavirus.m.pipedream.net/
+
+
+fetch('https://coronavirus.m.pipedream.net/')
+ .then(response => response.json())
+ .then(data => {
+ console.log(data);
+ })
+ .catch(error => {
+ console.error(error);
+ });
\ No newline at end of file
diff --git "a/Retos/Reto #15 - AUREBESH [F\303\241cil]/java/Cflorezp.java" "b/Retos/Reto #15 - AUREBESH [F\303\241cil]/java/Cflorezp.java"
new file mode 100644
index 0000000000..f2c9710acf
--- /dev/null
+++ "b/Retos/Reto #15 - AUREBESH [F\303\241cil]/java/Cflorezp.java"
@@ -0,0 +1,70 @@
+package reto15Aurebesh;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+
+/*
+ * Crea una función que sea capaz de transformar Español al lenguaje básico del universo
+ * Star Wars: el "Aurebesh".
+ * - Puedes dejar sin transformar los caracteres que no existan en "Aurebesh".
+ * - También tiene que ser capaz de traducir en sentido contrario.
+ *
+ * ¿Lo has conseguido? Nómbrame en twitter.com/mouredev y escríbeme algo en Aurebesh.
+ *
+ * ¡Que la fuerza os acompañe!
+ */
+public class Cflorezp {
+
+ public static void main(String[] args) {
+ System.out.println("**********************************************");
+ System.out.println("Bienvenido al traductor de Español a Aurebesh\n");
+ System.out.print("Escribe la palabra o frase que quieres traducir: ");
+
+ Scanner input = new Scanner(System.in);
+ String traducir = input.nextLine();
+
+ System.out.println("Traducción: \n" + caracterAurebesh(traducir.toLowerCase()));
+
+ }
+
+ public static String caracterAurebesh(String frase){
+ Map aurebesh = new HashMap<>(){{
+ put("a", "aurek"); put("b", "besh"); put("c", "cresh"); put("d", "dorn");
+ put("e", "esk"); put("f", "forn"); put("g", "grek"); put("h", "herf");
+ put("i", "isk"); put("j", "jenth"); put("k", "krill"); put("l", "leth");
+ put("m", "merm"); put("n", "nern"); put("o", "osk"); put("p", "peth");
+ put("q", "qek"); put("r", "resh"); put("s", "senth"); put("t", "trill");
+ put("u", "usk"); put("v", "vev"); put("w", "wesk"); put("x", "xesh");
+ put("y", "yirt"); put("z", "zerek"); put("ae", "enth"); put("ch","cherek");
+ put("eo", "onith"); put("kh", "krenth"); put("oo", "orenth"); put("sh", "sen");
+ put("th", "thesh"); put("gn", "nen"); put(" ", " "); put("ñ", "ñ");
+ }};
+
+ String duo = "";
+ String provisional = "";
+ StringBuilder creacionFrase = new StringBuilder();
+ for(int i = 0; i < frase.length(); i++){
+ if(i + 1 < frase.length()){
+ duo = frase.substring(i, i + 2);
+ provisional = aurebesh.get(duo);
+ if(provisional == null){
+ duo = frase.substring(i, i + 1);
+ provisional = aurebesh.get(duo) == null ? duo : aurebesh.get(duo);
+ creacionFrase.append(provisional);
+ }
+ else{
+ creacionFrase.append(provisional);
+ i++;
+ }
+ }else{
+ duo = frase.substring(i, i + 1);
+ provisional = aurebesh.get(duo);
+ creacionFrase.append(provisional);
+ }
+ }
+ return creacionFrase.toString();
+ }
+}
+
+
diff --git a/Retos/Reto #16 - LA ESCALERA [Media]/c++/OlvadisHernandezLedesma.cpp b/Retos/Reto #16 - LA ESCALERA [Media]/c++/OlvadisHernandezLedesma.cpp
new file mode 100644
index 0000000000..c220799985
--- /dev/null
+++ b/Retos/Reto #16 - LA ESCALERA [Media]/c++/OlvadisHernandezLedesma.cpp
@@ -0,0 +1,85 @@
+#include
+#include
+#include
+using std::string;
+using std::cout;
+using std::endl;
+using std::setw;
+using std::cin;
+
+void drawLadder(int n);
+void ladderpositiv(int n);
+void ladderNegativ(int n);
+
+int main() {
+ int escalon;
+ do {
+ cout << "Ingrese el numero de escalones: ";
+ cin >> escalon;
+
+ if (cin.fail() || cin.eof()) {
+ break;
+ }
+
+ drawLadder(escalon);
+ } while (escalon);
+
+ return 0;
+}
+
+void ladderNegativ(int n){
+ n=n*-1;
+ string parte1="_", parte2="|_";
+ for(int i=1; i<=n; i++){
+ if(i==1) {
+ cout<=1; i--){
+ if(i==n) {
+ for(int j=1; j<=i; j++){
+ cout<<" ";
+ }
+ cout<0) {
+ ladderPositiv(n);
+ }else if(n<0){
+ ladderNegativ(n);
+ }else{
+ cout<<"__"< 0) {
+ escaleraPositiva(numeroDeEscalones);
+ } else if (numeroDeEscalones < 0) {
+ escaleraNegativa(numeroDeEscalones);
+ } else {
+ System.out.println("__");
+ }
+ } catch (InputMismatchException e) {
+ System.out.println("El valor ingresado no es un número válido, por lo tanto no se dibujará nada");
+ }finally {
+ input.close();
+ }
+ }
+
+ public static void escaleraPositiva(int escalones) {
+ for (int i = escalones; i >= 0; i--) {
+ for (int j = 0; j < i; j++) {
+ System.out.print(" ");
+ }
+ if (i == escalones) {
+ System.out.println("_");
+ } else {
+ System.out.println("_|");
+ }
+ }
+ }
+
+ public static void escaleraNegativa(int escalones) {
+ escalones = escalones * -1;
+ for (int i = 0; i <= escalones; i++) {
+ for (int j = 0; j < i; j++) {
+ System.out.print(" ");
+ }
+ if (i == 0) {
+ System.out.println(" _");
+ } else {
+ System.out.println("|_");
+ }
+ }
+ }
+}
diff --git a/Retos/Reto #16 - LA ESCALERA [Media]/javascript/EmaPaul.js b/Retos/Reto #16 - LA ESCALERA [Media]/javascript/EmaPaul.js
new file mode 100644
index 0000000000..ae0f519d38
--- /dev/null
+++ b/Retos/Reto #16 - LA ESCALERA [Media]/javascript/EmaPaul.js
@@ -0,0 +1,39 @@
+/*
+ * Crea una función que dibuje una escalera según su número de escalones.
+ * - Si el número es positivo, será ascendente de izquiera a derecha.
+ * - Si el número es negativo, será descendente de izquiera a derecha.
+ * - Si el número es cero, se dibujarán dos guiones bajos (__).
+ *
+ * Ejemplo: 4
+ * _
+ * _|
+ * _|
+ * _|
+ * _|
+ *
+ */
+
+
+
+function escalones(numero){
+ let contadorPositivos = 1;
+ let contadorNegativos = -1
+ let escalera = "";
+
+ if(numero>0){
+ while(contadorPositivos<=numero){
+ escalera += ' '.repeat(numero - contadorPositivos) + '_|\n';
+ contadorPositivos++;
+ }
+ }else if(numero<0){
+ while(contadorNegativos>=numero){
+ escalera += ' '.repeat(Math.abs(contadorNegativos) - 1) + '|_\n';
+ contadorNegativos--;
+ }
+ }else {
+ escalera = '__';
+ }
+ return escalera
+}
+
+console.log(escalones(6));
diff --git a/Retos/Reto #16 - LA ESCALERA [Media]/python/jpirulo.py b/Retos/Reto #16 - LA ESCALERA [Media]/python/jpirulo.py
new file mode 100644
index 0000000000..2c21ae788a
--- /dev/null
+++ b/Retos/Reto #16 - LA ESCALERA [Media]/python/jpirulo.py
@@ -0,0 +1,29 @@
+class Staircase:
+ def __init__(self, steps: int):
+ self.steps = steps
+
+ def draw(self):
+ if self.steps > 0:
+ for step in range(self.steps + 1):
+ spaces = " " * (self.steps - step)
+ step_draw = "_" if step == 0 else "_|"
+ print(f"{spaces}{step_draw}")
+ elif self.steps < 0:
+ for step in range(abs(self.steps) + 1):
+ spaces = " " * ((step * 2) - 1)
+ step_draw = "_" if step == 0 else "|_"
+ print(f"{spaces}{step_draw}")
+ else:
+ print("__")
+
+staircase1 = Staircase(0)
+staircase2 = Staircase(4)
+staircase3 = Staircase(20)
+staircase4 = Staircase(-4)
+staircase5 = Staircase(-20)
+
+staircase1.draw()
+staircase2.draw()
+staircase3.draw()
+staircase4.draw()
+staircase5.draw()
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/dart/titoworlddev.dart" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/dart/titoworlddev.dart"
new file mode 100644
index 0000000000..2e607d1810
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/dart/titoworlddev.dart"
@@ -0,0 +1,61 @@
+/*
+ * ¡Estoy de celebración! He publicado mi primer libro:
+ * "Git y GitHub desde cero"
+ * - Papel: mouredev.com/libro-git
+ * - eBook: mouredev.com/ebook-git
+ *
+ * ¿Sabías que puedes leer información de Git y GitHub desde la gran
+ * mayoría de lenguajes de programación?
+ *
+ * Crea un programa que lea los últimos 10 commits de este repositorio y muestre:
+ * - Hash
+ * - Autor
+ * - Mensaje
+ * - Fecha y hora
+ *
+ * Ejemplo de salida:
+ * Commit 1 (el más reciente) | 12345A | MoureDev | Este es un commit | 24/04/2023 21:00
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+ */
+
+// import 'package:http/http.dart' as http;
+import 'dart:io';
+import 'dart:convert';
+
+const URL = 'https://api.github.com';
+const USER = 'mouredev';
+const REPO = 'retos-programacion-2023';
+
+void main() {
+ printCommits(10);
+}
+
+void printCommits(int commitsLength) async {
+ // final data = await http
+ // .get(Uri.parse('$URL/repos/$USER/$REPO/commits'))
+ // .then((res) => jsonDecode(res.body));
+
+ /* Aunque es mas facil con http, dependiendo de como y donde lo ejecutes se
+ puede hacer la peticion con dart:io ya que http necesita
+ un proyecto de dart para instalar las dependencias y poder usarlas
+ pero dart:io no lo necesita */
+ final data = await HttpClient()
+ .getUrl(Uri.parse('$URL/repos/$USER/$REPO/commits'))
+ .then((req) => req.close())
+ .then((res) => res.transform(utf8.decoder).join())
+ .then((res) => jsonDecode(res));
+
+ for (int i = 1; i <= commitsLength; i++) {
+ final hash = data[i]['sha'].substring(0, 7).toUpperCase();
+ final commit = data[i]['commit'];
+ final name = commit['author']['name'];
+ final message = commit['message'];
+ final date = DateTime.parse(commit['author']['date']);
+ final dateFormated =
+ '${date.day}/${date.month}/${date.year} ${date.hour}:${date.minute}';
+
+ print('Commit $i | $hash | $name | $message | $dateFormated\n\n');
+ }
+}
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/java/Qv1ko.java" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/java/Qv1ko.java"
new file mode 100644
index 0000000000..057c807f6f
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/java/Qv1ko.java"
@@ -0,0 +1,25 @@
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.ietf.jgss.GSSException;
+
+import java.io.File;
+import java.io.IOException;
+
+public class Qv1ko {
+
+ public static void main(String[] args) {
+ lastCommits();
+ }// main
+
+ private static void lastCommits() {
+ String repoPath = ".";
+ Git git = new Git(new FileRepositoryBuilder().setGitDir(new File(repoPath)).readEnvironment().findGitDir().build());
+ int num = 1;
+ for (RevCommit commit : git.log().setMaxCount(10).call()) {
+ System.out.println("Commit " + num + " | " + commit.getName() + " | " + commit.getAuthorIdent().getName() + " | " + commit.getFullMessage() + " | " + commit.getAuthorIdent().getWhen());
+ }
+ }
+
+}// class
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/LauraCastrillonMp.js" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/LauraCastrillonMp.js"
new file mode 100644
index 0000000000..a4ea26455d
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/LauraCastrillonMp.js"
@@ -0,0 +1,46 @@
+/*
+ * ¡Estoy de celebración! He publicado mi primer libro:
+ * "Git y GitHub desde cero"
+ * - Papel: mouredev.com/libro-git
+ * - eBook: mouredev.com/ebook-git
+ *
+ * ¿Sabías que puedes leer información de Git y GitHub desde la gran
+ * mayoría de lenguajes de programación?
+ *
+ * Crea un programa que lea los últimos 10 commits de este repositorio y muestre:
+ * - Hash
+ * - Autor
+ * - Mensaje
+ * - Fecha y hora
+ *
+ * Ejemplo de salida:
+ * Commit 1 (el más reciente) | 12345A | MoureDev | Este es un commit | 24/04/2023 21:00
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+*/
+
+async function getCommits() {
+ try {
+ const response = await fetch(`https://api.github.com/repos/mouredev/retos-programacion-2023/commits`);
+ const data = await response.json();
+ let commits = [];
+ for (let i = 0; i < 10; i++) {
+ commits.push({
+ commit: i + 1,
+ Hash: data[i].commit.tree.sha.slice(0, 7),
+ Autor: data[i].commit.author.name,
+ Mensaje: data[i].commit.message,
+ Fecha: data[i].commit.author.date
+ });
+ let mensaje = commits[i].Mensaje.replace(/\n/g, " "); // Para eliminar el salto de linea que hay en el mensaje del commit
+ console.log(`Commit: ${commits[i].commit} | ${commits[i].Hash} | ${commits[i].Autor} | ${mensaje} | ${commits[i].Fecha}`);
+ }
+ } catch (error) {
+ return console.log(error);
+ }
+}
+
+getCommits()
+
+
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/marcode24.js" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/marcode24.js"
index 7e1bb6ce70..e49cd3950e 100644
--- "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/marcode24.js"
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/marcode24.js"
@@ -36,3 +36,4 @@ const getCommits = ({ user, repo, limit = 10 }) => {
};
// Visita mi repo en GitHub para ver y correr los tests de este código --> https://github.com/marcode24/weekly-challenges
+getCommits("mouredev", "retos-programacion-2023")
\ No newline at end of file
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/raulg91.js" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/raulg91.js"
new file mode 100644
index 0000000000..236e57a907
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/raulg91.js"
@@ -0,0 +1,42 @@
+const https = require('https');
+
+
+function get_data() {
+
+ let data = [];
+ //Set request options
+ let options = {
+ headers : {
+ "User-Agent":"raulg91"
+ }
+ };
+
+ const req = https.get( "https://api.github.com/repos/mouredev/retos-programacion-2023/commits",options,(res)=>{
+ res.on('data', (chunk) => {
+ data.push(chunk);
+ });
+
+ res.on('end',()=>{
+ const commits = JSON.parse(Buffer.concat(data).toString());
+
+ for(let i=0;i<10;i++){
+ let message = commits[i].commit.message;
+ message = message.toString().replace(/\n/g,"");
+ let date = new Date(commits[i].commit.author.date);
+ let date_string = `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}`;
+ console.log(`Commit ${i+1} | ${commits[i].sha} | ${commits[i].commit.author.name} | ${message} | ${date_string}`);
+ }
+
+ });
+
+
+
+ }).on("error",(error)=>{
+ console.log("Error: " + error.message);
+ })
+
+ req.end();
+
+}
+
+get_data();
\ No newline at end of file
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/test0n3.js" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/test0n3.js"
new file mode 100644
index 0000000000..7aa9a86c32
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/javascript/test0n3.js"
@@ -0,0 +1,46 @@
+const https = require("https");
+
+const mouredev_commits = {
+ hostname: "api.github.com",
+ path: "/repos/mouredev/retos-programacion-2023/commits",
+ method: "GET",
+ headers: {
+ "User-Agent":
+ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.78 Safari/537.36",
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+};
+
+const getAPI = (uri) => {
+ https
+ .get(uri, (res) => {
+ let data = [];
+ res.on("data", (chunk) => {
+ data.push(chunk);
+ });
+ res.on("end", () => {
+ let commits = JSON.parse(Buffer.concat(data).toString());
+ let processed_commits = commits.slice(0, 10).map((commit, index) => {
+ let hash = commit.sha.slice(0, 6);
+ let author =
+ commit.author == null
+ ? commit.commit.author.name
+ : commit.author.login;
+ let message = commit.commit.message.replace(/\n\n/g, " - ");
+ let date = new Date(commit.commit.author.date).toLocaleString(
+ "es-PE"
+ );
+ return `Commit ${
+ index + 1
+ } | ${hash} | ${author} | ${message} | ${date}`;
+ });
+ console.log(processed_commits.join("\n"));
+ });
+ })
+ .on("error", (err) => {
+ console.log("Error:", err.message);
+ });
+};
+
+getAPI(mouredev_commits);
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/php/josea2r.php" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/php/josea2r.php"
new file mode 100644
index 0000000000..9a8e629642
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/php/josea2r.php"
@@ -0,0 +1,70 @@
+/*
+ * ¡Estoy de celebración! He publicado mi primer libro:
+ * "Git y GitHub desde cero"
+ * - Papel: mouredev.com/libro-git
+ * - eBook: mouredev.com/ebook-git
+ *
+ * ¿Sabías que puedes leer información de Git y GitHub desde la gran
+ * mayoría de lenguajes de programación?
+ *
+ * Crea un programa que lea los últimos 10 commits de este repositorio y muestre:
+ * - Hash
+ * - Autor
+ * - Mensaje
+ * - Fecha y hora
+ *
+ * Ejemplo de salida:
+ * Commit 1 (el más reciente) | 12345A | MoureDev | Este es un commit | 24/04/2023 21:00
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+ */
+
+ https://gist.github.com/travstoll/d6d72855b4184fbfc30f3a20a9adbb4c
+
+ //Auth Token para hacer uso del API (Añadir el tuyo creado previamente)
+ $token = "Añade tu Access Personal Token que puedes crear desde GitHub";
+
+ $url = "https://api.github.com/repos/mouredev/retos-programacion-2023/commits?per_page=10";
+
+ //Añadir la información necesaria para el uso de API (método y headers)
+ $opts = [
+ 'http' => [
+ 'method' => 'GET',
+ 'header' => [
+ 'User-Agent: PHP',
+ 'Authorization: Bearer ' . $token,
+ 'X-GitHub-Api-Version: 2022-11-28',
+ 'Content-type: application/x-www-form-urlencoded',
+ ],
+ ]
+ ];
+
+ //Inicializa file_get_contents
+ $context = stream_context_create($opts);
+
+ //Realiza el request a la página
+ $content = file_get_contents($url, false, $context);
+
+ //Convierte la información en Array
+ $response_array = json_decode($content, true);
+
+ $commit_number = array('commit' => 0);
+
+ //Luego de obtener la información del API podremos comenzar a obtener los datos de los commits
+ foreach($response_array as $commit) {
+
+ $commit_number['commit'] = $commit_number['commit'] + 1;
+
+ $sha = substr($commit['sha'], 0, 7);
+ $author_name = $commit['commit']['author']['name'];
+ $message = str_replace("\n", '', $commit['commit']['message']);
+ $time = date_format(date_create($commit['commit']['author']['date']), 'd/m/Y H:i');
+
+ echo "Commit {$commit_number['commit']} | " . $sha . " | " . $author_name . " | " . $message . " | " . $time . "\n";
+
+ }
+
+?>
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/php/omgslinux.php" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/php/omgslinux.php"
new file mode 100644
index 0000000000..b8e2662109
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/php/omgslinux.php"
@@ -0,0 +1,120 @@
+_repo;
+ }
+
+ public function setRepo($url): self
+ {
+ $this->_repo = $url;
+
+ return $this;
+ }
+
+ private function getCommitURL(): ?string
+ {
+ if (null!=$this->getRepo()) {
+ return $this->getRepo() . '/commits';
+ }
+
+ return null;
+ }
+
+ public function getCommits(int $number=10): array
+ {
+ $headerItems = [
+ 'Content-type:' => 'application/json',
+ 'Accept:' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
+ 'User-Agent:' => 'PHP',
+ ];
+ $header = "";
+ foreach ($headerItems as $item => $value) {
+ $header .= "$item $value\n";
+ }
+ $options = [
+ "http" => [
+ 'method' => 'GET',
+ 'header' => $header
+ ]
+ ];
+
+ $context = stream_context_create($options);
+ $data = [];
+ if (null!=$this->getCommitURL()) {
+ $url = $this->getCommitURL() . '?per_page=' . $number;
+ $this->_data = $data = json_decode(file_get_contents($url, false, $context), true);
+ }
+
+ return $data;
+ }
+
+ public function getCommitAuthor($commit)
+ {
+ return $commit['commit']['author']['name'];
+ }
+
+ public function getCommitDate($commit): string
+ {
+ $date = new DateTime($commit['commit']['author']['date']);
+
+ return $date->format('d/m/Y H:i');
+ }
+
+ public function getCommitHash($commit)
+ {
+ return substr($commit['sha'], 0, 7);
+ }
+
+ public function getCommitMessage($commit)
+ {
+ return str_replace("\n", '', $commit['commit']['message']);
+ }
+
+}
+
+$info = new gitInfo();
+$commits = $info
+ ->setRepo('https://api.github.com/repos/mouredev/retos-programacion-2023')
+ ->getCommits(10);
+
+$count = 0;
+foreach ($commits as $commit) {
+ $count++;
+ printf(
+ "Commit {%d} | %s | %s | %s | %s\n",
+ $count,
+ $info->getCommitHash($commit),
+ $info->getCommitAuthor($commit),
+ $info->getCommitMessage($commit),
+ $info->getCommitDate($commit)
+ );
+
+}
+
\ No newline at end of file
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/Bryan112094.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/Bryan112094.py"
new file mode 100644
index 0000000000..518963d376
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/Bryan112094.py"
@@ -0,0 +1,25 @@
+# ¡Estoy de celebración! He publicado mi primer libro:
+# "Git y GitHub desde cero"
+# - Papel: mouredev.com/libro-git
+# - eBook: mouredev.com/ebook-git
+# ¿Sabías que puedes leer información de Git y GitHub desde la gran
+# mayoría de lenguajes de programación?
+# Crea un programa que lea los últimos 10 commits de este repositorio y muestre:
+# - Hash
+# - Autor
+# - Mensaje
+# - Fecha y hora
+# Ejemplo de salida:
+# Commit 1 (el más reciente) | 12345A | MoureDev | Este es un commit | 24/04/2023 21:00
+# Se permite utilizar librerías que nos faciliten esta tarea.
+
+from git import Repo
+import pathlib
+
+def listCommits(numero):
+ repositorio = Repo(pathlib.Path(__file__).parent.resolve(), search_parent_directories=True)
+ commits = list(repositorio.iter_commits(repositorio.active_branch, max_count=numero))
+ for i in range(numero):
+ print(F"Commit {str(i + 1)}: {commits[i].hexsha}\n Autor: {commits[i].author.name}\n Mensaje: {commits[i].message.splitlines()[0]}\n Fecha y hora: {str(commits[i].committed_datetime)}\n")
+
+listCommits(10)
\ No newline at end of file
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/Engleonardorm7.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/Engleonardorm7.py"
new file mode 100644
index 0000000000..336727963b
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/Engleonardorm7.py"
@@ -0,0 +1,13 @@
+from github import Github
+
+g = Github("pon tu access token aqui...")
+repo = g.get_repo("mouredev/retos-programacion-2023")
+
+commits = repo.get_commits()[:10]
+
+for i, commit in enumerate(commits):
+ sha = commit.sha[:7]
+ author = commit.commit.author.name
+ message = commit.commit.message
+ date = commit.commit.author.date.strftime("%d/%m/%Y %H:%M")
+ print(f"Commit {i+1} | {sha} | {author} | {message} | {date}")
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/KevinED11.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/KevinED11.py"
new file mode 100644
index 0000000000..bd7cec3877
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/KevinED11.py"
@@ -0,0 +1,58 @@
+import requests
+
+
+from typing import Generator
+
+
+def get_repo_commits(repo: str) -> str:
+ return f"https://api.github.com/repos/{repo}/commits"
+
+
+def all_commits(repo_url: str) -> list[dict]:
+ try:
+ return requests.get(repo_url).json()
+ except requests.exceptions.RequestException as err:
+ print(err)
+
+
+def format_commits(commits: list[dict]) -> Generator:
+ return (f"commit #{str(i+1)} | hash={str(commit['sha'])} | Author={commit['commit']['author']['name']} | Message={commit['commit']['message']} | Date={commit['commit']['author']['date']}" for i, commit in enumerate(commits))
+
+
+def commits_to_show(number: int = 10) -> int:
+ try:
+ return abs(int(number))
+ except ValueError:
+ print(ValueError(
+ f"Invalid value for 'number': '{number}'. Please enter a valid integer."))
+
+
+def generate_commits(commits: Generator, number: int = 10, mode="DESC") -> list[str]:
+ mode = mode.upper()
+ commit_mode: tuple[str, str] = ("ASC", "DESC")
+
+ try:
+ if mode not in commit_mode:
+ raise ValueError(f"PLace a valide mode: {commit_mode}")
+ except ValueError as err:
+ print(err)
+
+ if mode == commit_mode[0]:
+ return [commit for commit in commits][:number]
+
+ return [commit for commit in commits][-number:]
+
+
+def main() -> None:
+ repo_to_use = get_repo_commits(repo="mouredev/retos-programacion-2023")
+ available_commits = all_commits(repo_url=repo_to_use)
+ formatted_commits = format_commits(commits=available_commits)
+ commits_number_to_show = commits_to_show(number="5")
+
+ commits = generate_commits(
+ formatted_commits, commits_number_to_show, mode="asc")
+ print(commits)
+
+
+if __name__ == "__main__":
+ main()
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/ingjavierpinilla.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/ingjavierpinilla.py"
new file mode 100644
index 0000000000..0a68333184
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/ingjavierpinilla.py"
@@ -0,0 +1,36 @@
+import requests
+
+
+class GithubService:
+ def __init__(self, repo):
+ self.repo = repo
+ self.base_url = f"https://api.github.com/repos/{self.repo}"
+
+ def get_commits(self, per_page=10):
+ url = f"{self.base_url}/commits"
+ params = {"per_page": per_page}
+ try:
+ response = requests.get(url, params=params)
+ response.raise_for_status()
+ except requests.exceptions.HTTPError as err:
+ raise SystemExit(err) from None
+ return response.json()
+
+ def print_commits(self, per_page=10):
+ commits = self.get_commits()
+ if not commits:
+ return None
+ for i, commit in enumerate(commits):
+ sha = commit.get("sha")
+ _commit = commit.get("commit")
+ author = _commit.get("author").get("name")
+ message = _commit.get("message").strip()
+ date = _commit.get("committer").get("date")
+ print(f"{i}. {sha} | {author} | {message} | {date}")
+ print()
+
+
+if __name__ == "__main__":
+ url = "mouredev/retos-programacion-2023"
+ github_service = GithubService(url)
+ print(github_service.print_commits())
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/jpirulo.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/jpirulo.py"
new file mode 100644
index 0000000000..c2415cb9f6
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/jpirulo.py"
@@ -0,0 +1,36 @@
+import requests
+import json
+
+class Commit:
+ def __init__(self, hash, author, message, date):
+ self.hash = hash
+ self.author = author
+ self.message = message
+ self.date = date
+
+class GitHubAPI:
+ def __init__(self, owner, repo):
+ self.owner = owner
+ self.repo = repo
+ self.url = f"https://api.github.com/repos/{owner}/{repo}/commits?per_page=10"
+
+ def get_last_commits(self):
+ response = requests.get(self.url)
+ commits_json = json.loads(response.text)
+ commits = []
+ for commit_json in commits_json:
+ hash = commit_json['sha'][:6]
+ author = commit_json['commit']['author']['name']
+ message = commit_json['commit']['message']
+ date = commit_json['commit']['author']['date'][:-6]
+ commit = Commit(hash, author, message, date)
+ commits.append(commit)
+ return commits
+
+# Ejemplo de uso
+github_api = GitHubAPI("Mouredev", "retos-programacion-2023")
+print('Ultimos 10 Commits')
+
+commits = github_api.get_last_commits()
+for i, commit in enumerate(commits):
+ print(f"Commit {i+1} | {commit.hash} | {commit.author} | {commit.message} | {commit.date}")
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/juanppdev.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/juanppdev.py"
new file mode 100644
index 0000000000..7c5f33cd33
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/juanppdev.py"
@@ -0,0 +1,5 @@
+import git
+
+repoCloned = git.Repo("retos-programacion-2023")
+
+print(repoCloned.git.log())
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/mouredev.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/mouredev.py"
new file mode 100644
index 0000000000..7c04a72531
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/mouredev.py"
@@ -0,0 +1,7 @@
+import git
+
+commit_counter = 1
+
+for commit in list(git.Repo(".").iter_commits())[:10]:
+ print(f"Commit {commit_counter} | {commit.hexsha} | {commit.author.name} | {commit.message} | {commit.authored_datetime}".replace("\n", ""))
+ commit_counter += 1
\ No newline at end of file
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/pyramsd.py" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/pyramsd.py"
new file mode 100644
index 0000000000..2f00278bfc
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/python/pyramsd.py"
@@ -0,0 +1,10 @@
+import git
+import pathlib
+
+if __name__ == '__main__':
+ repo = git.Repo(pathlib.Path(__file__).parent.resolve(), search_parent_directories=True)
+ commits = list(repo.iter_commits(repo.active_branch, max_count=10))
+ for i in range(len(commits)):
+ to_print = "Commit " + str(i + 1) + " : " + commits[i].hexsha + " \n Autor: " + commits[i].author.name + " \n Mensaje: " + commits[i].message.splitlines()[0] + " \n Fecha y hora: " + str(commits[i].committed_datetime) + "\n"
+ print(to_print)
+
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/ruby/test0n3.rb" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/ruby/test0n3.rb"
new file mode 100644
index 0000000000..a06b8b035b
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/ruby/test0n3.rb"
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'uri'
+require 'net/http'
+require 'json'
+require 'time'
+
+# class GetAPI
+class GetAPI
+ MOUREDEV_GITHUB = 'https://api.github.com/repos/mouredev/retos-programacion-2023/commits'
+
+ def pick_commits
+ uri = URI(MOUREDEV_GITHUB)
+ res = Net::HTTP.get_response(uri)
+ print_api_resp(JSON.parse(res.body).first(10)) if res.is_a?(Net::HTTPSuccess)
+ end
+
+ def print_api_resp(commits)
+ commits.map.with_index do |commit, index|
+ hash = commit['sha'][0, 6]
+ author = commit['author'].nil? ? commit['commit']['author']['name'] : commit['author']['login']
+ message = commit['commit']['message'].gsub(/\n\n/, ' - ')
+ date = Time.parse(commit['commit']['author']['date']).localtime.strftime('%d/%m/%Y %H:%M:%S')
+ "Commit #{index + 1} | #{hash} | #{author} | #{message} | #{date}"
+ end
+ end
+end
+
+puts GetAPI.new.pick_commits
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/KevinED11.ts" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/KevinED11.ts"
new file mode 100644
index 0000000000..05e69729ce
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/KevinED11.ts"
@@ -0,0 +1,81 @@
+import axios from "axios"
+
+interface DataCommit {
+ sha: string;
+ commit: {
+ author: {
+ name: string;
+ date: string;
+ };
+ message: string;
+ };
+}
+
+
+class GitHub {
+ private userName: string;
+ private repoName: string
+ private baseUrl: string
+
+ constructor(userName: string, repoName: string) {
+ this.userName = userName
+ this.repoName = repoName
+ this.baseUrl = `https://api.github.com/repos/${this.userName}/${this.repoName}`
+ }
+
+ async getCommits(): Promise{
+ try {
+ const response = await axios.get(`${this.baseUrl}/commits`)
+ return response.data
+ } catch (err) {
+ console.error(err)
+ return []
+ }
+
+ }
+
+ async formatCommits(showCommits: number) {
+ showCommits = Math.abs(showCommits)
+ const allCommits: DataCommit[] | [] = await this.getCommits()
+ const formattedCommits = allCommits.map((commit: DataCommit, indice: number) => {
+ return {
+ commit: indice + 1,
+ sha: commit.sha,
+ author: commit.commit.author.name,
+ date: commit.commit.author.date,
+ message: commit.commit.message.replace("\n", "")
+
+ }
+ })
+
+ return formattedCommits.slice(0, showCommits)
+ }
+
+
+ get nameRepo(): string {
+ return this.repoName
+ }
+
+ get userNameRepository(): string {
+ return this.userName
+ }
+
+
+
+
+}
+
+const main = async (): Promise => {
+ const github = new GitHub("mouredev", "retos-programacion-2023")
+ const commits = await github.getCommits()
+ const commits2 = await github.formatCommits(-10)
+ console.log(commits2)
+ console.log(commits2.length)
+ console.log(github.nameRepo)
+ console.log(github.userNameRepository)
+
+}
+
+
+
+main()
\ No newline at end of file
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/manurgdev.ts" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/manurgdev.ts"
new file mode 100644
index 0000000000..75778acd7e
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/manurgdev.ts"
@@ -0,0 +1,125 @@
+const getLastCommits = async (params: getLastCommitsParams = {}) => {
+ const { repositoryName, numberOfCommits } = { repositoryName: 'mouredev/retos-programacion-2023', numberOfCommits: 10, ...params };
+ const url = `https://api.github.com/repos/${repositoryName}/commits?per_page=${numberOfCommits}`;
+ let commitsApiData: GithubApiCommit[] = await fetch(
+ url,
+ {
+ headers: { 'Accept': 'application/vnd.github.v3+json' },
+ method: 'GET'
+ }
+ )
+ .then(response => response.json())
+ .catch((error: Error) => console.log(error));
+ const commits: CommitsInfo[] = commitsApiData.map(commitInfo => {
+ return {
+ hash: commitInfo.commit.tree.sha,
+ author: commitInfo.commit.author.name,
+ message: commitInfo.commit.message,
+ date: new Date(commitInfo.commit.author.date).toLocaleString()
+ }
+ });
+
+ printCommitsInfo(commits);
+}
+
+const printCommitsInfo = (commits: CommitsInfo[]) => {
+ commits.forEach((commit, index) => {
+ console.log(`Commit ${index + 1} | ${commit.hash} | ${commit.author} | ${commit.message} | ${commit.date}`);
+ console.log('-------------------------------');
+ });
+}
+
+getLastCommits();
+
+
+/** Types */
+
+type CommitsInfo = {
+ hash: string,
+ author: string,
+ message: string,
+ date: string
+};
+
+type getLastCommitsParams = {
+ repositoryName?: string,
+ numberOfCommits?: number
+};
+
+/** START Types extracted from QuickType */
+type GithubApiCommit = {
+ sha: string;
+ node_id: string;
+ commit: Commit;
+ url: string;
+ html_url: string;
+ comments_url: string;
+ author: GithubAuthor | null;
+ committer: GithubAuthor | null;
+ parents: Parent[];
+}
+
+type GithubAuthor = {
+ login: string;
+ id: number;
+ node_id: string;
+ avatar_url: string;
+ gravatar_id: string;
+ url: string;
+ html_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ starred_url: string;
+ subscriptions_url: string;
+ organizations_url: string;
+ repos_url: string;
+ events_url: string;
+ received_events_url: string;
+ type: Type;
+ site_admin: boolean;
+}
+
+enum Type {
+ User = "User",
+}
+
+type Commit = {
+ author: CommitAuthor;
+ committer: CommitAuthor;
+ message: string;
+ tree: Tree;
+ url: string;
+ comment_count: number;
+ verification: Verification;
+}
+
+type CommitAuthor = {
+ name: string;
+ email: string;
+ date: Date;
+}
+
+type Tree = {
+ sha: string;
+ url: string;
+}
+
+type Verification = {
+ verified: boolean;
+ reason: Reason;
+ signature: null | string;
+ payload: null | string;
+}
+
+enum Reason {
+ Unsigned = "unsigned",
+ Valid = "valid",
+}
+
+type Parent = {
+ sha: string;
+ url: string;
+ html_url: string;
+}
+/** END Types extracted from QuickType */
diff --git "a/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/zerchito.ts" "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/zerchito.ts"
new file mode 100644
index 0000000000..fd539d3511
--- /dev/null
+++ "b/Retos/Reto #17 - GIT Y GITHUB [Dif\303\255cil]/typescript/zerchito.ts"
@@ -0,0 +1,48 @@
+/*
+ * ¡Estoy de celebración! He publicado mi primer libro:
+ * "Git y GitHub desde cero"
+ * - Papel: mouredev.com/libro-git
+ * - eBook: mouredev.com/ebook-git
+ *
+ * ¿Sabías que puedes leer información de Git y GitHub desde la gran
+ * mayoría de lenguajes de programación?
+ *
+ * Crea un programa que lea los últimos 10 commits de este repositorio y muestre:
+ * - Hash
+ * - Autor
+ * - Mensaje
+ * - Fecha y hora
+ *
+ * Ejemplo de salida:
+ * Commit 1 (el más reciente) | 12345A | MoureDev | Este es un commit | 24/04/2023 21:00
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+ */
+type RepositoryCommit ={
+ hash: string,
+ author: string,
+ message: string,
+ date: Date
+}
+const repositoryName = 'mouredev/retos-programacion-2023';
+const NUMBER_OF_COMMITS = 10;
+async function readCommits(repositoryName: string):Promise {
+ const url = `https://api.github.com/repos/${repositoryName}/commits`
+ let commitsData = await fetch(url)
+ .then(response => response.json())
+ .catch(error => console.log(error));
+ let commits = commitsData.slice(0, NUMBER_OF_COMMITS);
+ commits = commits.map(commitInfo => {
+ return {
+ hash: commitInfo.commit.tree.sha,
+ author: commitInfo.commit.author.name,
+ message: commitInfo.commit.message,
+ date: new Date(commitInfo.commit.author.date)
+ }
+ });
+ console.log(commits)
+ return commits;
+}
+
+readCommits(repositoryName);
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/c#/borazuwarah.cs" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/c#/borazuwarah.cs"
new file mode 100644
index 0000000000..d19e5b5980
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/c#/borazuwarah.cs"
@@ -0,0 +1,36 @@
+/*
+ * El día 128 del año celebramos en la comunidad el "Hola Mundo day"
+ * Vamos a hacer "web scraping" sobre su sitio web: https://holamundo.day
+ *
+ * Crea un programa que se conecte a la web del evento e imprima únicamente la agenda de eventos
+ * del día 8. Mostrando hora e información de cada uno.
+ * Ejemplo: "16:00 | Bienvenida"
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+ */
+
+using System;
+using HtmlAgilityPack;
+
+namespace Reto18
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ string url = "https://holamundo.day";
+ var web = new HtmlWeb();
+ var doc = web.Load(url);
+
+ var events = doc.DocumentNode.SelectNodes("//blockquote[@class='BlockquoteElement___StyledBlockquote-sc-1dtx4ci-0 slate-BlockquoteElement notion-quote unset-width']");
+
+ foreach (var event in events)
+ {
+ if (event.InnerText.Contains("|"))
+ Console.WriteLine(event.InnerText);
+ }
+ Console.ReadKey();
+ }
+ }
+}
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/ejercicio.md" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/ejercicio.md"
new file mode 100644
index 0000000000..e702fb587a
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/ejercicio.md"
@@ -0,0 +1,23 @@
+# Reto #18: Web scraping
+#### Dificultad: Difícil | Publicación: 01/05/23 | Corrección: 11/05/23
+
+## Enunciado
+
+```
+/*
+ * El día 128 del año celebramos en la comunidad el "Hola Mundo day"
+ * Vamos a hacer "web scraping" sobre su sitio web: https://holamundo.day
+ *
+ * Crea un programa que se conecte a la web del evento e imprima únicamente la agenda de eventos
+ * del día 8. Mostrando hora e información de cada uno.
+ * Ejemplo: "16:00 | Bienvenida"
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+ */
+```
+#### Tienes toda la información extendida sobre los retos de programación semanales en **[retosdeprogramacion.com/semanales2023](https://retosdeprogramacion.com/semanales2023)**.
+
+Sigue las **[instrucciones](../../README.md)**, consulta las correcciones y aporta la tuya propia utilizando el lenguaje de programación que quieras.
+
+> Recuerda que cada semana se publica un nuevo ejercicio y se corrige el de la semana anterior en directo desde **[Twitch](https://twitch.tv/mouredev)**. Tienes el horario en la sección "eventos" del servidor de **[Discord](https://discord.gg/mouredev)**.
\ No newline at end of file
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/javascript/marcode24.js" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/javascript/marcode24.js"
new file mode 100644
index 0000000000..76ede82962
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/javascript/marcode24.js"
@@ -0,0 +1,43 @@
+/*
+ * El día 128 del año celebramos en la comunidad el "Hola Mundo day"
+ * Vamos a hacer "web scraping" sobre su sitio web: https://holamundo.day
+ *
+ * Crea un programa que se conecte a la web del evento e imprima únicamente la agenda de eventos
+ * del día 8. Mostrando hora e información de cada uno.
+ * Ejemplo: "16:00 | Bienvenida"
+ *
+ * Se permite utilizar librerías que nos faciliten esta tarea.
+ *
+ */
+
+const puppeteer = require('puppeteer');
+
+const SITE = 'https://holamundo.day/';
+
+const getShedule = async () => {
+ const browser = await puppeteer.launch({
+ headless: 'new',
+ });
+ const page = await browser.newPage();
+ await page.goto(SITE);
+ const title = await page.title();
+ const content = await page.$$('article.notion-page-content-inner');
+ const events = content[7]; // 7 is the index of the events section
+
+ const quoteElements = await events.$$('blockquote.notion-quote');
+ const eventInfo = await Promise.all(quoteElements.map(async (quoteElement) => {
+ const spanElement = await quoteElement.$('span[data-slate-string="true"]');
+ const text = await quoteElement.evaluate((el) => el.textContent, spanElement);
+ return text;
+ }));
+ const schedule = `${title}\n\n`.concat(eventInfo
+ .map((event) => event.replace(/\n/g, ' '))
+ .join('\n'));
+ if (browser) await browser.close();
+ return schedule;
+};
+
+getShedule().then((schedule) => console.log(schedule));
+
+// Visita mi repo en GitHub para ver y correr los tests de este código --> https://github.com/marcode24/weekly-challenges
+
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/kotlin/fernanapps.kt" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/kotlin/fernanapps.kt"
new file mode 100644
index 0000000000..75888e79f0
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/kotlin/fernanapps.kt"
@@ -0,0 +1,67 @@
+import java.net.URL
+/**
+.......................... Printing .............................................
+@author: FernanApps
+
+ >_ Agenda 8 de mayo | “Hola Mundo” day
+
+ 16:00 | Bienvenida
+ 16:30 | De Junior a Junior: cómo abrirte paso | Antonio Rodríguez
+ 17:00 | El Rol del Analista Funcional en el Ciclo de Desarrollo | Luisina de Paula
+ 17:30 | Taller: Git y Github para el mundo | Ehud Aguirre
+ 18:00 | Mesa redonda
+ 18:30 | Descanso + Sorteos
+ 19:00 | Clean Code: cómo dormir más y mejor | Fran Sierra
+ 19:30 | Abrazando al fracaso | Afor Digital
+ 20:00 | Taller: Descubre el mundo de machine learning | Stefy Mojica
+ 20:30 | Elevator pitch
+ 21:00 | Invitados
+ 21:30 | Mi primer año como Desarrollador a los 45 años | Gerardo Arrieta
+ 22:00 | Taller: Testing, más que código | Manu Rodríguez
+ 22:30 | Descanso + Sorteos
+ 23:00 | Despedida
+
+ */
+fun main() {
+
+ val pageUrl = "https://holamundo.day/"
+ val title8May = "Agenda 8 de mayo"
+
+ val htmlString = downloadPage(pageUrl)
+ val articleBlocks = extractHTMLTagBlock("article", htmlString)
+ val articleBlock8May = articleBlocks.filter { it.contains(title8May) }.toString()
+ val articleBlock8MayFilter = Regex("
+ println(event)
+ }
+}
+
+fun downloadPage(pageUrl: String): String {
+ val html = URL(pageUrl).openConnection().apply {
+ setRequestProperty("User-Agent", "Mozilla/5.0")
+ }.getInputStream().bufferedReader().use {
+ it.readText()
+ }
+ return html
+}
+
+fun extractHTMLTagBlock(tag: String, html: String): List {
+ val regex = Regex("<$tag.*?$tag>", RegexOption.DOT_MATCHES_ALL)
+ val blocks: List = regex.findAll(html).map {
+ it.value
+ }.toList()
+ return blocks
+}
+
+fun extractHTMLTagContent(input: String): String {
+ val regex = "<[^>]*>".toRegex()
+ return regex.replace(input, "")
+}
\ No newline at end of file
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/JoseMHU.py" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/JoseMHU.py"
new file mode 100644
index 0000000000..41456c66f6
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/JoseMHU.py"
@@ -0,0 +1,23 @@
+from requests_html import HTMLSession
+import re
+URL = "https://holamundo.day/"
+
+
+def get_agenda(n_agenda: int):
+ session = HTMLSession()
+ web_data = session.get(URL).html.find(".BlockquoteElement___StyledBlockquote-sc-1dtx4ci-0")
+ count = 0
+ for element in web_data:
+ try:
+ valid_content = re.match("[\d:|]", element.text).string
+ if re.search("Bienvenida", valid_content):
+ count += 1
+ if count == n_agenda:
+ print(valid_content)
+ except AttributeError:
+ pass
+
+
+if __name__ == "__main__":
+ # En get_agenda se puede especificar 1 = 1 era agenda (4 de mayo) // 2 = 2da agenda (8 de mayo)
+ get_agenda(2)
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/albertovf.py" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/albertovf.py"
new file mode 100644
index 0000000000..bcb3ae02a9
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/albertovf.py"
@@ -0,0 +1,16 @@
+from bs4 import BeautifulSoup
+import requests
+
+url = "https://holamundo.day/"
+
+page = requests.get(url)
+soup = BeautifulSoup(page.content, 'html.parser')
+
+day = soup.find_all('h1')[-2]
+
+if day:
+ print(day.text)
+ next_element = day.find_next_sibling()
+ while next_element is not None and next_element.name == 'blockquote':
+ print(next_element.text)
+ next_element = next_element.find_next_sibling()
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/blackriper.py" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/blackriper.py"
new file mode 100644
index 0000000000..38e71de1c4
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/blackriper.py"
@@ -0,0 +1,26 @@
+from requests_html import HTMLSession
+"""
+instalar libreria pip install requests_html
+
+"""
+
+
+
+def main():
+ # iniciar objeto de sesion y obtener la pagina
+ session=HTMLSession()
+ page=session.get("https://holamundo.day")
+
+ """
+ al inspecionar la pagina puedes ver que cada evento de la
+ charla usa una etiqueta blockquote solo hay que ver cuantos elementos son
+ y traer el rango en este caso [19:34]
+ postd: los conte de manera manual para saber el rango debe de haber una mejor manera
+ de hacerlo
+ """
+
+ for event in page.html.find("blockquote")[19:34]:
+ print(event.text)
+
+if __name__=='__main__':
+ main()
\ No newline at end of file
diff --git "a/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/pyramsd.py" "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/pyramsd.py"
new file mode 100644
index 0000000000..dd2157ac52
--- /dev/null
+++ "b/Retos/Reto #18 - WEB SCRAPING [Dif\303\255cil]/python/pyramsd.py"
@@ -0,0 +1,18 @@
+from bs4 import BeautifulSoup
+import requests
+
+url = "https://holamundo.day/"
+page = requests.get(url)
+soup = BeautifulSoup(page.content, "html.parser")
+
+main = soup.find_all("blockquote", class_="BlockquoteElement___StyledBlockquote-sc-1dtx4ci-0 slate-BlockquoteElement notion-quote unset-width")
+
+eventos = []
+
+for i in main:
+ i = i.text
+ eventos.append(i)
+
+print("EVENTOS 8 DE MAYO:\n-------------------")
+for j in eventos[19:]:
+ print(j)
diff --git a/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/javascript/abanoj.js b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/javascript/abanoj.js
new file mode 100644
index 0000000000..bda09bb4a3
--- /dev/null
+++ b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/javascript/abanoj.js
@@ -0,0 +1,51 @@
+/*
+ * 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 reto2 = partido => {
+ let p1 = 0, p2= 0;
+ const POINTS = ['Love', 15, 30, 40];
+
+ if (partido.some( e => e !== 'P1' & e !== 'P2'))
+ throw TypeError("This method only accepts 'P1' and 'P2' as inputs.");
+
+ for(e of partido){
+ if(e === 'P1'){
+ p1++;
+ } else if (e === 'P2') {
+ p2++;
+ }
+ if(p1 >= 3 & p1 === p2) console.log('Deuce');
+ if(p1 >= 4 & p1 === p2 + 1){console.log('Ventaja P1'); continue}
+ if(p1 >= 4 & p1 >= p2 + 2){console.log('Ha ganado el P1'); return}
+ if(p2 >= 4 & p2 === p1 + 1){console.log('Ventaja P2'); continue};
+ if(p2 >= 4 & p2 >= p1 + 2){console.log('Ha ganado el P2'); return}
+
+ if (p1 < 3 || ((p1 === 3 || p2 === 3) & p1 !== p2)){
+ console.log(`${POINTS[p1]} - ${POINTS[p2]}`)
+ }
+ }
+}
+
+// reto2(['P1', 'P1', 'P2', 'P2', 'P1', 'P2', 'P1', 'P1']);
+// console.log('================')
+// reto2(['P2', 'P2', 'P1', 'P1', 'P2', 'P1', 'P2', 'P2']);
+// console.log('================')
+// reto2(['P2','P2','P2','P1','P2','P1']);
+// console.log('================')
+// reto2(['P1','P1','P1','P2','P1','P2']);
\ No newline at end of file
diff --git a/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/saurivane.py b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/saurivane.py
new file mode 100644
index 0000000000..205614f94e
--- /dev/null
+++ b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/saurivane.py
@@ -0,0 +1,48 @@
+"""/*
+ * 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.
+ */
+"""
+
+puntuacion = {0:"Love", 1:"15", 2:"30", 3:"40"}
+player1 = 0
+player2 = 0
+
+secuencia = ["P1", "P1", "P2", "P2", "P1", "P2", "P1", "P1"]
+
+for i in secuencia:
+ if i == "P1":
+ player1 = player1+1
+ else:
+ player2 = player2+1
+
+ if player1 == 3 and player2 == 3:
+ print("Deuce")
+ elif player1 >= 4 or player2 >= 4:
+ diff = player1 - player2
+ if diff == 0:
+ print("Deuce")
+ elif diff == 1:
+ print("Ventaja P1")
+ elif diff == -1:
+ print("Ventaja P2")
+ elif diff >= 2:
+ print("Ha ganado el P1")
+
+ else: print("Ha ganado P2")
+ else:
+ print(f"{puntuacion[player1]} - {puntuacion[player2]}")
\ No newline at end of file
diff --git a/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/sublian.py b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/sublian.py
index 8daeb81169..1ef769cbbe 100644
--- a/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/sublian.py
+++ b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/python/sublian.py
@@ -1,8 +1,7 @@
-@@ -0,0 +1,71 @@
-# Reto #2: EL PARTIDO DE TENIS
-#### Dificultad: Media | Publicación: 09/01/23 | Corrección: 16/01/23
-"""Enunciado
+"""# Reto #2: EL PARTIDO DE TENIS
+#### Dificultad: Media | Publicación: 09/01/23 | Corrección: 16/01/23
+
/*
* 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
@@ -30,7 +29,7 @@ def partido(scores):
print("")
for score in scores:
-
+
if score=="P1":
score_p1+=1
elif score=="P2":
@@ -42,28 +41,28 @@ def partido(scores):
if score_p1 == score_p2 and score_p1 > 0:
print("Deuce")
elif score_p1>3 or score_p2>3:
-
+
if score_p1 == score_p2 - 2:
print("Ganador P2 \n")
return()
-
+
elif score_p2 == score_p1 - 2:
print("Ganador P1 \n")
return()
-
+
elif score_p1 == score_p2 - 1:
print("Ventaja P2")
- continue
-
+ continue
+
elif score_p2 == score_p1 - 1:
print("Ventaja P1")
- continue
-
+ continue
+
else:
print(f'{points[score_p1]} - {points[score_p2]}')
if __name__ == '__main__':
-
+
print("Primer partido")
partido(["P1", "P1", "P2", "P2", "P1", "P2", "P1", "P1", "P1"])
print("Segundo partido")
diff --git a/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/typescript/zerchito.ts b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/typescript/zerchito.ts
new file mode 100644
index 0000000000..b83e9e544e
--- /dev/null
+++ b/Retos/Reto #2 - EL PARTIDO DE TENIS [Media]/typescript/zerchito.ts
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+function resumeMatch(matchPlays:string[]): void {
+ const players = {
+ P1: 0,
+ P2: 0
+ }
+ matchPlays.forEach(play => {
+ players[play]++;
+ // a partir de 3 puntos los empates son deuce
+ if (players.P1 < 3 && players.P2 < 3 && !(players.P1 + players.P2 === 6) ) {
+ console.log(`${transformScore(players.P1)} - ${transformScore(players.P2)}`);
+ } else{
+ if (players.P1 === players.P2) {
+ console.log('Deuce');
+ }
+ if (Math.abs(players.P1 - players.P2) === 1){
+ console.log(`Ventaja ${play}`);
+ } else {
+ console.log(`Ha ganado el ${play}`);
+ }
+ }
+ })
+}
+
+function transformScore (score: number): string {
+ switch(score){
+ case 0: return 'Love';
+ case 1: return '15';
+ case 2: return '30';
+ case 3: return '40';
+ default: return `${score}`;
+ }
+}
+
+resumeMatch(['P1', 'P1', 'P2', 'P2', 'P1', 'P2', 'P1', 'P1']);
\ No newline at end of file
diff --git "a/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/javascript/abanoj.js" "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/javascript/abanoj.js"
new file mode 100644
index 0000000000..f1c5878b98
--- /dev/null
+++ "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/javascript/abanoj.js"
@@ -0,0 +1,41 @@
+/*
+ * 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)
+ */
+
+const rangeGenerator = (start=0, stop, step=1) => {
+ return Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step));
+}
+
+const retoTres = (length = 8, capital = false, numbers = false, symbols = false ) => {
+ let options = rangeGenerator(97,122).map(e => String.fromCharCode(e));
+ let password = '';
+
+ if(length < 8) length = 8;
+ if(length > 16) length = 16;
+
+ if(capital)
+ options = options.concat(rangeGenerator(65,90).map(e => String.fromCharCode(e)));
+
+ if(numbers)
+ options = options.concat(rangeGenerator(48,57).map(e => String.fromCharCode(e)));
+
+ if(symbols){
+ options = options.concat(rangeGenerator(33,47).map(e => String.fromCharCode(e)));
+ options = options.concat(rangeGenerator(58,64).map(e => String.fromCharCode(e)));
+ options = options.concat(rangeGenerator(91,96).map(e => String.fromCharCode(e)));
+ }
+
+ console.log(options);
+ for (let i = 0; i < length; i++) {
+ password += options[Math.floor(Math.random() * options.length)];
+ }
+ return password;
+}
+
+retoTres()
\ No newline at end of file
diff --git "a/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/python/saurivane.py" "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/python/saurivane.py"
new file mode 100644
index 0000000000..c22b8887f5
--- /dev/null
+++ "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/python/saurivane.py"
@@ -0,0 +1,46 @@
+"""
+/*
+ * 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)
+ */
+ """
+
+import random
+import string
+
+def contraseña(long, mayus, num, sim):
+
+ contraseña = ""
+ azar = "abcdefghijklmnñopqrstuvwxyz"
+
+ if mayus == "S":
+ azar = azar + "ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"
+
+ if num == "S":
+ azar = azar + "0123456789"
+
+ if sim == "S":
+ azar = azar + "ºª\\!|@·#$%&/()=?\'¿¡€^`[*+]¨´><;,:._-"
+
+ if long == "A" or "8":
+ for i in range(0,8):
+ contraseña = contraseña + random.choice(azar)
+ elif long == "B" or "16":
+ for i in range(0,16):
+ contraseña = contraseña + random.choice(azar)
+
+ return contraseña
+
+longitud = (input("Elige la longitud de la contraseña entre A)8 o B)16: "))
+mayusculas = input("Con mayusculas? S/N: ")
+numeros = input("Con númros?S/N: ")
+simbolos = input("Con símbolos?S/N: ")
+
+print(contraseña(longitud.upper(), mayusculas.upper(), numeros.upper(), simbolos.upper()))
+
+
\ No newline at end of file
diff --git "a/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/python/sublian.py" "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/python/sublian.py"
new file mode 100644
index 0000000000..8b5825f087
--- /dev/null
+++ "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/python/sublian.py"
@@ -0,0 +1,72 @@
+"""
+Reto #3: EL GENERADOR DE CONTRASEÑAS
+ Dificultad: Media | Publicación: 16/01/23 | Corrección: 23/01/23
+
+Enunciado
+ * 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)
+"""
+
+# ficheros necesarios
+import secrets
+import string
+
+def leer_entero(texto="Indique el tamaño de la contraseña: "):
+ entrada = input(texto)
+ try:
+ entrada = int(entrada)
+ return entrada
+ except ValueError:
+ print ("La entrada es incorrecta: escribe un numero entero")
+ return 0
+
+
+def leer_cadena(texto):
+ entrada = input(texto).upper()
+ if entrada.isalpha() and entrada == "S":
+ return entrada
+ elif entrada =="N":
+ return False
+ else:
+ print("La entrada es incorrecta: escribe un caracter [s/n]")
+ leer_cadena(texto)
+
+if __name__ == '__main__':
+
+ print("..::Reto #3: EL GENERADOR DE CONTRASEÑAS::..")
+ alphabet=""
+
+ clave_tam = leer_entero()
+ if clave_tam>7 and clave_tam<17:
+ res_letras= leer_cadena("Desea que posea letras mayúsculas [s/n]: ")
+ if res_letras =="S":
+ letters = string.ascii_uppercase
+ alphabet +=letters
+
+ res_numeros= leer_cadena("Desea que posea numeros [s/n]: ")
+ if res_numeros =="S":
+ digits = string.digits
+ alphabet +=digits
+
+ res_simbolos= leer_cadena("Desea que posea símbolos [s/n]: ")
+ if res_simbolos =="S":
+ special_chars = string.punctuation
+ alphabet +=special_chars
+
+ if res_letras or res_numeros or res_simbolos:
+ # generate a password string
+ pwd = ''
+ for i in range(clave_tam):
+ pwd += ''.join(secrets.choice(alphabet))
+ print(pwd)
+ else:
+ print("No ha selecionado Letras, Numeros ni simbolos. No se puede generar la contraseña!")
+ else:
+ print("No se puede generar la contraseña. El rango permitido es de 8 a 16")
+
+#alphabet = letters + digits + special_chars
diff --git "a/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/typescript/zerchito.ts" "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/typescript/zerchito.ts"
new file mode 100644
index 0000000000..87e983a658
--- /dev/null
+++ "b/Retos/Reto #3 - EL GENERADOR DE CONTRASE\303\221AS [Media]/typescript/zerchito.ts"
@@ -0,0 +1,34 @@
+/*
+ * 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)
+ */
+const CHARACTERS_LIB = {
+ alphabet: "abcdefghijklmnopqrstuvwxyz",
+ numbers: "0123456789",
+ symbols: "&/\\^=?!@#$%*+.,:;|()[]{}<>-_"
+}
+
+function generatePassword (
+ numberOfCharacters: number,
+ enableUpperCase: boolean,
+ enableNumbers: boolean,
+ enableSimbols: boolean
+) {
+ let password = '';
+ let library = CHARACTERS_LIB.alphabet;
+ if(enableUpperCase) library += CHARACTERS_LIB.alphabet.toUpperCase();
+ if(enableNumbers) library += CHARACTERS_LIB.numbers;
+ if(enableSimbols) library += CHARACTERS_LIB.symbols;
+ for(let number = 0; number < numberOfCharacters; number++){
+ const random = Math.random() * library.length-1;
+ password = password + library.charAt(random);
+ }
+ return password;
+}
+
+console.log(generatePassword(16, true, true, true));
diff --git a/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/javascript/abanoj.js b/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/javascript/abanoj.js
new file mode 100644
index 0000000000..d8a41ff28e
--- /dev/null
+++ b/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/javascript/abanoj.js
@@ -0,0 +1,50 @@
+/*
+ * 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"
+ */
+
+const esPrimo = num => {
+ let primo = (num<2)? false: true;
+ for(let i=2; i {
+ let a = 0;
+ let b = 1;
+ while (b {
+ let result = '';
+ if(esPrimo(num)){
+ result += `${num} es primo, `;
+ } else {
+ result += `${num} no es primo, `;
+ }
+
+ if(esFibonacci(num)){
+ result += 'es fibonacci ';
+ } else {
+ result += 'no es fibonacci ';
+ }
+
+ if(num%2 === 0){
+ result += 'y es par.';
+ } else {
+ result += 'y no es par.';
+ }
+ return result;
+}
\ No newline at end of file
diff --git a/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/python/sublian.py b/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/python/sublian.py
new file mode 100644
index 0000000000..e1d2db4bfd
--- /dev/null
+++ b/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/python/sublian.py
@@ -0,0 +1,39 @@
+"""
+Reto #4: PRIMO, FIBONACCI Y PAR
+ Dificultad: Media | Publicación: 23/01/23 | Corrección: 30/01/23
+ * 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"
+"""
+import math
+
+def is_perfect_square(number):
+ sqrt = int(math.sqrt(number))
+ return sqrt*sqrt==number
+
+def check_prime_fibonacci_pair(number):
+
+ result =f"{number}: "
+ #primo
+ if number > 1:
+ for index in range(2,number):
+ if number%index==0:
+ result +="No es primo,"
+ break
+ else:
+ result +="Es primo,"
+ else:
+ result +="No es primo,"
+
+ #fibonacci
+ result += " Es Fibonacci" if number>0 and(is_perfect_square(5*number*number+4) or is_perfect_square(5*number*number-4)) else " No es Fibonacci"
+
+ #par
+ result += ", es par!" if number %2 ==0 else ", es impar!"
+ print(result)
+
+if __name__ == '__main__':
+
+ value= int(input("Ingrese valor a evaluar: "))
+ check_prime_fibonacci_pair(value)
\ No newline at end of file
diff --git a/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/typescript/zerchito.ts b/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/typescript/zerchito.ts
new file mode 100644
index 0000000000..ab483f0b13
--- /dev/null
+++ b/Retos/Reto #4 - PRIMO, FIBONACCI Y PAR [Media]/typescript/zerchito.ts
@@ -0,0 +1,55 @@
+/*
+ * 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"
+ */
+class NumberChecker {
+
+ fibonacciNumbers: number[] = [1 , 1];
+
+ checkNummber(num: number) {
+ const primeCheck = this.#isPrime(num);
+ const fibonacciCheck = this.#isFibonacci(num);
+ const evenCheck = this.#isEven(num);
+ return `${num} ${primeCheck}, ${fibonacciCheck} y ${evenCheck}`;
+ }
+
+ #isPrime(num: number): string{
+ let primeCheck = true;
+ for (let div = 2; num<= Math.sqrt(num); div++) {
+ if(num%div === 0){
+ primeCheck = false;
+ break;
+ }
+ }
+ return primeCheck ? 'es primo': 'no es primo';
+ }
+
+ #isFibonacci(num: number): string {
+ let lastIndex = this.fibonacciNumbers.length - 1;
+ let lastFibonacci = this.fibonacciNumbers[lastIndex];
+ let fiboCheck = false;
+ if (this.fibonacciNumbers.includes(num)) {
+ fiboCheck = true;
+ } else if (num > lastFibonacci) {
+ while (num > lastFibonacci) {
+ const newFibonacci = lastFibonacci + this.fibonacciNumbers[lastIndex-1];
+ lastFibonacci = newFibonacci;
+ this.fibonacciNumbers.push(newFibonacci);
+ lastIndex++;
+ fiboCheck = num === newFibonacci;
+ }
+ }
+
+ return fiboCheck ? 'es fibonacci' : 'no es fibonacci';
+ }
+
+ #isEven(num: number): string {
+ return num % 2 ? 'es par' : 'es impar';
+ }
+}
+
+const checker = new NumberChecker();
+console.log(checker.checkNummber(2))
+console.log(checker.checkNummber(7))
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/bash/mjordanaam.sh" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/bash/mjordanaam.sh"
new file mode 100755
index 0000000000..9ef72daac2
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/bash/mjordanaam.sh"
@@ -0,0 +1,10 @@
+#!/bin/bash
+# /*
+# * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+# * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+# * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+# *
+# * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+# */
+echo "Hello World!"
+
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c#/zerchito.cs" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c#/zerchito.cs"
new file mode 100644
index 0000000000..b031db43de
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c#/zerchito.cs"
@@ -0,0 +1,8 @@
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+Console.WriteLine("Hello world");
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c++/mjordanaam.cpp" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c++/mjordanaam.cpp"
new file mode 100644
index 0000000000..c516c026a5
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c++/mjordanaam.cpp"
@@ -0,0 +1,16 @@
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+#include
+
+using namespace std;
+
+int main() {
+ cout << "Hello World!" << endl;
+
+ return 0;
+}
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c/mjordanaam.c" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c/mjordanaam.c"
new file mode 100644
index 0000000000..d900e4d5c5
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/c/mjordanaam.c"
@@ -0,0 +1,14 @@
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+#include
+
+int main() {
+ printf("Hello World!");
+
+ return 0;
+}
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/dart/mjordanaam.dart" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/dart/mjordanaam.dart"
new file mode 100644
index 0000000000..ea4f4dced8
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/dart/mjordanaam.dart"
@@ -0,0 +1,3 @@
+void main(){
+ print("Hello World!");
+}
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/java/mjordanaam.java" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/java/mjordanaam.java"
new file mode 100644
index 0000000000..7a36042452
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/java/mjordanaam.java"
@@ -0,0 +1,13 @@
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+
+public class mjordanaam {
+ public static void main(String[] args) {
+ System.out.println("Hello World!");
+ }
+}
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/javascript/mjordanaam.js" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/javascript/mjordanaam.js"
new file mode 100644
index 0000000000..46ad21466e
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/javascript/mjordanaam.js"
@@ -0,0 +1,8 @@
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+console.log("Hello World!");
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/php/mjordanaam.php" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/php/mjordanaam.php"
new file mode 100644
index 0000000000..e7f4922b93
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/php/mjordanaam.php"
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/caroAM22.py" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/caroAM22.py"
new file mode 100644
index 0000000000..44159b3954
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/caroAM22.py"
@@ -0,0 +1 @@
+print("Hello world")
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/drifterDev.py" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/drifterDev.py"
new file mode 100644
index 0000000000..63334d8adb
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/drifterDev.py"
@@ -0,0 +1 @@
+print("Hola mundo!")
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/martin-aq.py" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/martin-aq.py"
new file mode 100644
index 0000000000..0f074f67ac
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/martin-aq.py"
@@ -0,0 +1,4 @@
+def saludar():
+ print("Hola Mundo!")
+
+saludar()
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/mjordanaam.py" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/mjordanaam.py"
new file mode 100644
index 0000000000..d7c433941c
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/python/mjordanaam.py"
@@ -0,0 +1,10 @@
+"""
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+"""
+print("Hello World!")
\ No newline at end of file
diff --git "a/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/typescript/mjordanaam.ts" "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/typescript/mjordanaam.ts"
new file mode 100644
index 0000000000..46ad21466e
--- /dev/null
+++ "b/Retos/Reto #5 - HOLA MUNDO [F\303\241cil]/typescript/mjordanaam.ts"
@@ -0,0 +1,8 @@
+/*
+ * Escribe un !Hola Mundo! en todos los lenguajes de programación que puedas.
+ * Seguro que hay algún lenguaje que te llama la atención y nunca has utilizado,
+ * o quizás quieres dar tus primeros pasos... ¡Pues este es el momento!
+ *
+ * A ver quién se atreve con uno de esos lenguajes que no solemos ver por ahí...
+ */
+console.log("Hello World!");
\ No newline at end of file
diff --git a/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/javascript/abanoj.js b/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/javascript/abanoj.js
new file mode 100644
index 0000000000..b6b49c8795
--- /dev/null
+++ b/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/javascript/abanoj.js
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+const retoSeis = games => {
+ const rules = {
+ "✂️": ["📄", "🦎"],
+ "📄": ["🗿", "🖖"],
+ "🗿": ["🦎", "✂️"],
+ "🦎": ["🖖", "📄"],
+ "🖖": ["✂️", "🗿"],
+ };
+
+ let player1 = 0, player2 = 0;
+
+ for (const game of games) {
+ let player1_game = game[0];
+ let player2_game = game[1];
+
+ if (player1_game === player2_game) continue;
+
+ if(rules[player1_game].includes(player2_game)){
+ player1++;
+ } else if (rules[player2_game].includes(player1_game)){
+ player2++;
+ }
+ }
+
+ return (player1 === player2)? 'Tie': (player1 > player2)? 'Player 1': 'Player 2';
+};
+
+console.log(retoSeis([["🗿", "✂️"]]));
+console.log(retoSeis([["🗿", "🗿"]]));
+console.log(retoSeis([["✂️", "🗿"]]));
+console.log(retoSeis([["🗿","✂️"], ["✂️","🗿"], ["📄","✂️"]]));
+console.log(retoSeis([["🗿", "🗿"], ["🗿", "🗿"], ["🗿", "🗿"], ["🗿", "🗿"]]));
+console.log(retoSeis([["🖖", "🗿"], ["✂️", "📄"], ["🗿", "🗿"], ["🦎", "🖖"]]));
\ No newline at end of file
diff --git a/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/kotlin/jaennova.kt b/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/kotlin/jaennova.kt
new file mode 100644
index 0000000000..f8620c29ac
--- /dev/null
+++ b/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/kotlin/jaennova.kt
@@ -0,0 +1,57 @@
+fun main() {
+ val rounds = listOf(
+ Pair("🗿", "✂️"),
+ Pair("✂️", "🗿"),
+ Pair("📄", "✂️")
+ )
+
+ val result = calculateWinner(rounds)
+
+ println("El ganador es $result")
+}
+
+fun calculateWinner(rounds: List>): String {
+ var player1Score = 0
+ var player2Score = 0
+
+ rounds.forEach { round ->
+ val player1Choice = round.first
+ val player2Choice = round.second
+
+ when {
+ player1Choice == player2Choice -> {
+ // Empate
+ }
+ player1Choice == "🗿" && (player2Choice == "✂️" || player2Choice == "🦎") -> {
+ // Gana jugador 1
+ player1Score++
+ }
+ player1Choice == "✂️" && (player2Choice == "📄" || player2Choice == "🦎") -> {
+ // Gana jugador 1
+ player1Score++
+ }
+ player1Choice == "📄" && (player2Choice == "🗿" || player2Choice == "🖖") -> {
+ // Gana jugador 1
+ player1Score++
+ }
+ player1Choice == "🦎" && (player2Choice == "📄" || player2Choice == "🖖") -> {
+ // Gana jugador 1
+ player1Score++
+ }
+ player1Choice == "🖖" && (player2Choice == "🗿" || player2Choice == "✂️") -> {
+ // Gana jugador 1
+ player1Score++
+ }
+ else -> {
+ // Gana jugador 2
+ player2Score++
+ }
+ }
+ }
+
+ return when {
+ player1Score > player2Score -> "Player 1"
+ player2Score > player1Score -> "Player 2"
+ else -> "Tie"
+ }
+}
diff --git a/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/typescript/zerchito.ts b/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/typescript/zerchito.ts
new file mode 100644
index 0000000000..8ce4965381
--- /dev/null
+++ b/Retos/Reto #6 - PIEDRA, PAPEL, TIJERA, LAGARTO, SPOCK [Media]/typescript/zerchito.ts
@@ -0,0 +1,40 @@
+/*
+ * 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.
+*/
+
+const RULES = {
+ '🗿': ['✂️', '🦎'],
+ '📄': ['🗿', '🖖'],
+ '✂️': ['📄', '🦎'],
+ '🦎': ['🖖', '📄'],
+ '🖖': ['✂️', '🗿']
+};
+
+type PosiblePlays = '🗿' | '📄' | '✂️' | '🦎' | '🖖';
+
+type PlayTuple = [PosiblePlays, PosiblePlays];
+
+type ResultType = 'Player 2' | 'Player 1' | 'Tie';
+
+function calcResult(plays: PlayTuple[]): ResultType {
+ let score1 = 0;
+ let score2 = 0;
+ plays.forEach(play=> {
+ if(RULES[play[0]].includes(play[1])) {
+ score1++;
+ } else if(play[0] !== play[1]){
+ score2++;
+ }
+ })
+ const player = score1 > score2 ? 1 : 2;
+ return score1 === score2 ? 'Tie' : `Player ${player}`;
+}
+
+console.log(calcResult([["🗿","✂️"], ["✂️","🗿"], ["📄","✂️"]]));
diff --git a/Retos/Reto #7 - EL SOMBRERO SELECCIONADOR [Media]/kotlin/jaennova.kt b/Retos/Reto #7 - EL SOMBRERO SELECCIONADOR [Media]/kotlin/jaennova.kt
new file mode 100644
index 0000000000..52c332732e
--- /dev/null
+++ b/Retos/Reto #7 - EL SOMBRERO SELECCIONADOR [Media]/kotlin/jaennova.kt
@@ -0,0 +1,38 @@
+fun main() {
+ val preguntas = arrayOf(
+ "¿Cuál es tu asignatura favorita?",
+ "¿Qué cualidad valoras más en una persona?",
+ "¿Qué lugar prefieres para estudiar?",
+ "¿Cuál es tu mayor miedo?",
+ "¿Qué cualidad te define mejor?"
+ )
+
+ val respuestas = arrayOf(
+ arrayOf("Astronomía", "Historia de la Magia", "Herbología", "Encantamientos"),
+ arrayOf("Valentía", "Astucia", "Lealtad", "Inteligencia"),
+ arrayOf("La biblioteca", "La sala común", "El invernadero", "El lago negro"),
+ arrayOf("Las arañas", "El fracaso", "El rechazo", "La oscuridad"),
+ arrayOf("Valentía", "Astucia", "Lealtad", "Inteligencia")
+ )
+
+ val casas = arrayOf("Gryffindor", "Slytherin", "Hufflepuff", "Ravenclaw")
+ val puntajes = IntArray(casas.size)
+
+ for (i in preguntas.indices) {
+ println(preguntas[i])
+ for (j in respuestas[i].indices) {
+ println("${j+1}. ${respuestas[i][j]}")
+ }
+ print("Respuesta: ")
+ val respuesta = readLine()?.toIntOrNull() ?: 0
+ for (j in casas.indices) {
+ puntajes[j] += if (respuesta == j+1) 2 else 0
+ puntajes[j] += if (respuesta == (j+1) % 4 + 1) 1 else 0
+ puntajes[j] -= if (respuesta == (j+2) % 4 + 1) 1 else 0
+ puntajes[j] -= if (respuesta == (j+3) % 4 + 1) 2 else 0
+ }
+ }
+
+ val casaGanadora = casas[puntajes.indices.maxByOrNull { puntajes[it] } ?: 0]
+ println("¡Felicidades! Has sido seleccionado para la casa de $casaGanadora.")
+}
diff --git a/Retos/Reto #8 - EL GENERADOR PSEUDOALEATORIO [Media]/javascript/giovanyosorio.js b/Retos/Reto #8 - EL GENERADOR PSEUDOALEATORIO [Media]/javascript/giovanyosorio.js
new file mode 100644
index 0000000000..7e5d012ec7
--- /dev/null
+++ b/Retos/Reto #8 - EL GENERADOR PSEUDOALEATORIO [Media]/javascript/giovanyosorio.js
@@ -0,0 +1,15 @@
+/*
+ * 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...
+ */
+
+function randomNumber()
+{
+ let date = new Date();
+ return date.getTime() % 100
+ // console.log(date.getTime() % 100)
+
+}
+console.log("This is a random value:", randomNumber());
\ No newline at end of file
diff --git "a/Retos/Reto #9 - HETEROGRAMA, ISOGRAMA Y PANGRAMA [F\303\241cil]/javascript/giovanyosorio.js" "b/Retos/Reto #9 - HETEROGRAMA, ISOGRAMA Y PANGRAMA [F\303\241cil]/javascript/giovanyosorio.js"
new file mode 100644
index 0000000000..d98fd92400
--- /dev/null
+++ "b/Retos/Reto #9 - HETEROGRAMA, ISOGRAMA Y PANGRAMA [F\303\241cil]/javascript/giovanyosorio.js"
@@ -0,0 +1,67 @@
+/*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.
+ */
+//Es una palabra o frase que no contiene ninguna letra repetida.1
+
+function heterograma(palabra) {
+ var abecedario = "abcdefghijklmnñopqrstuvwxyz";
+ var palabra = palabra.toLowerCase();
+ var heterograma = true;
+ for (var i = 0; i < abecedario.length; i++) {
+ var contador = 0;
+ for (var j = 0; j < palabra.length; j++) {
+ if (abecedario[i] == palabra[j]) {
+ contador++;
+ }
+ }
+ if (contador > 1) {
+ heterograma = false;
+ }
+ }
+ if (heterograma) {
+ console.log("La palabra " + palabra + " es un heterograma");
+ } else {
+ console.log("La palabra " + palabra + " no es un heterograma");
+ }
+}
+
+heterograma("murcielago");
+
+function esIsograma(cadena) {
+ cadena = cadena.toLowerCase();
+ let contador = {};
+ for (let i = 0; i < cadena.length; i++) {
+ let letra = cadena[i];
+
+ if (contador[letra]) {
+ return false;
+ }
+ contador[letra] = true;
+ }
+
+ return true;
+}
+
+esIsograma("acondicionar")
+
+function esPangrama(cadena) {
+ // Convertir la cadena a minúsculas para hacer la comparación de caracteres más fácil
+ cadena = cadena.toLowerCase();
+ // Crear un objeto para llevar la cuenta de la cantidad de veces que aparece cada letra en la cadena
+ let contador = {};
+ // Recorrer cada letra de la cadena
+ for (let i = 0; i < cadena.length; i++) {
+ let letra = cadena[i];
+ // Si la letra es una letra del alfabeto, agregarla al objeto contador
+ if (/[a-z]/.test(letra)) {
+ contador[letra] = true;
+ }
+ }
+ // Si el objeto contador tiene 26 propiedades (una para cada letra del alfabeto), entonces la cadena es un pangrama
+ return Object.keys(contador).length === 26;
+}
+
+
+
+esPangrama(" Benjamín pidió una bebida de kiwi y fresa. Noé, sin vergüenza, la más exquisita champaña del menú.")
\ No newline at end of file