diff --git a/README.md b/README.md index bede3ae..6a343b7 100644 --- a/README.md +++ b/README.md @@ -82,8 +82,7 @@ Tienes toda la información extendida sobre los retos de programación semanales * **#47** - 21/11/22 - [`VOCAL MÁS COMÚN`](https://github.com/mouredev/Weekly-Challenge-2022-Swift/blob/main/WeeklyChallenge2022.playground/Pages/Challenge47.xcplaygroundpage/Contents.swift) * **#48** - 28/11/22 - [`EL CALENDARIO DE ADEVIENTO 2022`](https://github.com/mouredev/Weekly-Challenge-2022-Swift/blob/main/WeeklyChallenge2022.playground/Pages/Challenge48.xcplaygroundpage/Contents.swift) * **#49** - 05/12/22 - [`EL DETECTOR DE HANDLES`](https://github.com/mouredev/Weekly-Challenge-2022-Swift/blob/main/WeeklyChallenge2022.playground/Pages/Challenge49.xcplaygroundpage/Contents.swift) -* **#50** - 12/12/22 - [`LA ENCRIPTACIÓN DE KARACA`](https://github.com/mouredev/Weekly-Challenge-2022-Swift/blob/main/WeeklyChallenge2022.playground/Pages/Challenge50.xcplaygroundpage/Contents.swift) -* **#51** - 19/12/22 - `Publicación nuevo reto...` +* **#50** - 12/12/22 - `Publicación nuevo reto...` @@ -161,4 +160,4 @@ Soy ingeniero de software desde hace más de 12 años. Desde hace 4 años combin ### En mi perfil de GitHub tienes más información -[![Web](https://img.shields.io/badge/GitHub-MoureDev-14a1f0?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev) \ No newline at end of file +[![Web](https://img.shields.io/badge/GitHub-MoureDev-14a1f0?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/mouredev) diff --git a/WeeklyChallenge2022.playground/Pages/Challange4.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challange4.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..d960c28 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challange4.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,50 @@ +import Foundation + +/* + * Reto #4 + * ÁREA DE UN POLÍGONO + * Fecha publicación enunciado: 24/01/22 + * Fecha publicación resolución: 31/01/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea UNA ÚNICA FUNCIÓN (importante que sólo sea una) que sea capaz de calcular y retornar el área de un polígono. + * - La función recibirá por parámetro sólo UN polígono a la vez. + * - Los polígonos soportados serán Triángulo, Cuadrado y Rectángulo. + * - Imprime el cálculo del área de un polígono de cada tipo. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +struct Polygon { + private var hasFourVertices: Bool + private var sideA: Double + private var sideB: Double + private var sideC: Double + + init(hasFourVertices:Bool, sideA: Double, sideB: Double = 0.0, sideC: Double = 0.0) { + self.hasFourVertices = hasFourVertices + self.sideA = sideA + self.sideB = (sideB == 0.0) ? sideA : sideB + self.sideC = (sideC == 0.0) ? self.sideB : sideC + } + + func getArea() -> Double { + if(hasFourVertices) { + return sideA * sideB + } else { + let semiperimeter = (sideA + sideB + sideC) / 2.0 + return sqrt(semiperimeter * (semiperimeter - sideA) * (semiperimeter - sideB) * (semiperimeter - sideC)) + } + } +} + +print(Polygon.init(hasFourVertices: true, sideA: 4).getArea()) +print(Polygon.init(hasFourVertices: true, sideA: 7, sideB: 4).getArea()) +print(Polygon.init(hasFourVertices: false, sideA: 3, sideB: 4, sideC: 5).getArea()) +print(Polygon.init(hasFourVertices: false, sideA: 3, sideB: 4).getArea()) // isosceles +print(Polygon.init(hasFourVertices: false, sideA: 3).getArea()) // equilateral diff --git a/WeeklyChallenge2022.playground/Pages/Challenge0.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge0.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..3d5be62 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge0.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,32 @@ +import Foundation + +/* + * Reto #0 + * EL FAMOSO "FIZZ BUZZ" + * Fecha publicación enunciado: 27/12/21 + * Fecha publicación resolución: 03/01/22 + * Dificultad: FÁCIL + * + * 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". + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🗓reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ +//let startTime = NSDate() +(1...100).forEach { num in + if(num % 5 == 0) { + print("\(num % 3 == 0 ? "fizz" : "")buzz") + } else if(num % 3 == 0) { + print("fizz") + } else { + print(num) + } +} +//print("execution time: \(NSDate().timeIntervalSince(startTime as Date) * 1000) ms") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge0.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge0.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..9ec6d27 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge0.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,35 @@ +import Foundation + +/* + * Reto #0 + * EL FAMOSO "FIZZ BUZZ" + * Fecha publicación enunciado: 27/12/21 + * Fecha publicación resolución: 03/01/22 + * Dificultad: FÁCIL + * + * Enunciado: Escribe un programa en Swift 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". + * + * Resuelto: Sí + " Iteracciones: 1 + * Explicación: El código utiliza un bucle for para recorrer los números del 1 al 100. Para cada número, se comprueba si es múltiplo de 3 y de 5, de 3 o de 5, y se imprime el número sustituido por la palabra correspondiente, o bien se imprime el número sin modificar si no es múltiplo de ninguno de los dos números. + * + */ + +for number in 1...100 { + if number % 3 == 0 && number % 5 == 0 { + // El número es múltiplo de 3 y de 5 + print("fizzbuzz") + } else if number % 3 == 0 { + // El número es múltiplo de 3 + print("fizz") + } else if number % 5 == 0 { + // El número es múltiplo de 5 + print("buzz") + } else { + // El número no es múltiplo ni de 3 ni de 5 + print(number) + } +} diff --git a/WeeklyChallenge2022.playground/Pages/Challenge1.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge1.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..3919f1d --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge1.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,37 @@ +import Foundation + +/* + * Reto #1 + * ¿ES UN ANAGRAMA? + * Fecha publicación enunciado: 03/01/22 + * Fecha publicación resolución: 10/01/22 + * Dificultad: MEDIA + * + * Enunciado: Escribe una función que reciba dos palabras (String) y retorne verdadero o falso (Bool) según sean o no anagramas. + * Un Anagrama consiste en formar una palabra reordenando TODAS las letras de otra palabra inicial. + * NO hace falta comprobar que ambas palabras existan. + * Dos palabras exactamente iguales no son anagrama. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func areAnagrams(wordA: String, wordB: String) -> Bool { + return wordA.count == wordB.count && (wordA.lowercased().enumerated().filter { (index, c) in + String(c) == String(Array(wordB)[index]).lowercased() || // que cumpla que TODAS las letras están en otra posición (reordenadas) + wordA.split(separator: c).count != wordB.split(separator: c).count + }.isEmpty) +} + +print(areAnagrams(wordA: "Roma", wordB: "")) +print(areAnagrams(wordA: "Roma", wordB: "Roma")) +print(areAnagrams(wordA: "Roma", wordB: "romana")) +print(areAnagrams(wordA: "Roma", wordB: "Peru")) +print(areAnagrams(wordA: "Roma", wordB: "ramo")) +print(areAnagrams(wordA: "Roma", wordB: "mora")) +print(areAnagrams(wordA: "Roma", wordB: "moar")) +print(areAnagrams(wordA: "Roma", wordB: "amor")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge1.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge1.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..50374f7 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge1.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,64 @@ +import Foundation + +/* + * Reto #1 + * ¿ES UN ANAGRAMA? + * Fecha publicación enunciado: 03/01/22 + * Fecha publicación resolución: 10/01/22 + * Dificultad: MEDIA + * + * Enunciado: Escribe una función en Swift que reciba dos palabras (String) y retorne verdadero o falso (Bool) según sean o no anagramas. + * - Un Anagrama consiste en formar una palabra reordenando TODAS las letras de otra palabra inicial. + * - NO hace falta comprobar que ambas palabras existan. + * - Dos palabras exactamente iguales no son anagrama. + * + * Resuelto: No, en los casos en los que debe devolver falso a veces devuelve true. + * Explicación: Para resolver este problema, podríamos utilizar un diccionario para contar la cantidad de ocurrencias de cada letra en cada palabra. Luego, comparar los dos diccionarios para ver si son iguales. Si lo son, entonces las palabras son anagramas. + * Nota: no exige poner el nombre de los parámetros de la función. Utiliza tabulación de 2 espacios. + * + */ + +func esAnagrama(_ palabra1: String, _ palabra2: String) -> Bool { + // Primero, convertimos las palabras a minúsculas + let palabra1 = palabra1.lowercased() + let palabra2 = palabra2.lowercased() + + // Creamos un diccionario vacío para contar las ocurrencias de cada letra + var contador1 = [Character: Int]() + var contador2 = [Character: Int]() + + // Recorremos las dos palabras y contamos las ocurrencias de cada letra + for letra in palabra1 { + contador1[letra, default: 0] += 1 + } + for letra in palabra2 { + contador2[letra, default: 0] += 1 + } + + // Comparamos los diccionarios para ver si son iguales + return contador1 == contador2 +} + +// ChatGPT +// Debería devolver verdadero +esAnagrama("casa", "acas") +// Debería devolver falso +esAnagrama("casa", "casa") +esAnagrama("casa", "saca") +esAnagrama("casa", "baso") + +// Brais +print(esAnagrama("amor", "roma")) + +// Jaime +print(esAnagrama("Roma", "")) +print(esAnagrama("Roma", "Roma")) +print(esAnagrama("Roma", "romana")) +print(esAnagrama("Roma", "Peru")) +print(esAnagrama("Roma", "ramo")) +print(esAnagrama("Roma", "mora")) +print(esAnagrama("Roma", "moar")) +print(esAnagrama("Roma", "amor")) + + + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge10.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge10.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..ab2e949 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge10.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,52 @@ +import Foundation + +/* + * Reto #10 + * EXPRESIONES EQUILIBRADAS + * Fecha publicación enunciado: 07/03/22 + * Fecha publicación resolución: 14/03/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa que comprueba si los paréntesis, llaves y corchetes de una expresión están equilibrados. + * - Equilibrado significa que estos delimitadores se abren y cieran en orden y de forma correcta. + * - Paréntesis, llaves y corchetes son igual de prioritarios. No hay uno más importante que otro. + * - Expresión balanceada: { [ a * ( c + d ) ] - 5 } + * - Expresión no balanceada: { a * ( c + d ) ] - 5 } + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func isBalanced(expression: String) -> Bool { + let openBrackets = ["{","(","["] + let closeBrackets = ["}",")","]"] + let onlyBrackets = expression.filter{ openBrackets.contains(String($0)) || closeBrackets.contains(String($0)) } + + if(onlyBrackets.count == 2) { + return (onlyBrackets == "{}" || onlyBrackets == "()" || onlyBrackets == "[]") + } else { + let firstCloseBracketIndex = onlyBrackets.firstIndex(where: { closeBrackets.contains(String($0)) } ) + if(firstCloseBracketIndex == nil || onlyBrackets[...firstCloseBracketIndex!].count < 2) { + return false + } else { + let currentCouple = String(onlyBrackets[onlyBrackets.index(firstCloseBracketIndex!, offsetBy: -1).. Bool { + // Crea una pila para guardar los delimitadores abiertos + var stack = [String]() + + // Itera sobre cada caracter en la expresión + for character in expression { + // Si el caracter es un delimitador abierto, agrégalo a la pila + if delimiters.keys.contains(String(character)) { + stack.append(String(character)) + } + // Si el caracter es un delimitador cerrado, comprueba si se corresponde con el último delimitador abierto en la pila + else if delimiters.values.contains(String(character)) { + // Si la pila está vacía o el último delimitador abierto no se corresponde con el delimitador cerrado, la expresión no es equilibrada + if stack.isEmpty || delimiters[stack.last!] != String(character) { + return false + } + // Si el delimitador cerrado se corresponde con el último delimitador abierto en la pila, elimina el delimitador abierto de la pila + stack.removeLast() + } + } + + // Si la pila está vacía al final de la iteración, significa que todos los delimitadores abiertos fueron cerrados en orden y de forma correcta, por lo que la expresión es equilibrada + return stack.isEmpty +} + +// Ejemplos de expresiones equilibradas +print(isBalanced("{ [ a * ( c + d ) ] - 5 }")) +print(isBalanced("[ 1 + 2 ] + { 3 - 4 }")) + +// Brais cases +print(isBalanced("{a + b [c] * (2x2)}}}}")) // false +print(isBalanced("{ [ a * ( c + d ) ] - 5 }")) // true +print(isBalanced("{ a * ( c + d ) ] - 5 }")) // false +print(isBalanced("{a^4 + (((ax4)}")) // false +print(isBalanced("{ ] a * ( c + d ) + ( 2 - 3 )[ - 5 }")) // false +print(isBalanced("{{{{{{(}}}}}}")) // false +print(isBalanced("(a")) // false + +// Jaime cases +print(isBalanced("{ [ a * ( c + d ) ] - 5 }")) // true +print(isBalanced("[()]{}{[()()]()}")) // true +print(isBalanced("{[{}{}]}[()]")) // true +print(isBalanced("{{}{}}")) // true +print(isBalanced("[]{}()")) // true +print(isBalanced("a+2")) // true +print(isBalanced("{ a * ( c + d ) ] - 5 }")) // false +print(isBalanced("{()}[)")) // false +print(isBalanced("[(])")) // false +print(isBalanced("{(})")) // false +print(isBalanced("{")) // false + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge10.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge10.xcplaygroundpage/Contents.swift index cebcb04..141be7e 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge10.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Challenge10.xcplaygroundpage/Contents.swift @@ -47,6 +47,7 @@ func isBalanced(expression: String) -> Bool { } } } +} return stack.isEmpty } diff --git a/WeeklyChallenge2022.playground/Pages/Challenge11.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge11.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..2737480 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge11.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,34 @@ +import Foundation + +/* + * Reto #11 + * ELIMINANDO CARACTERES + * Fecha publicación enunciado: 14/03/22 + * Fecha publicación resolución: 21/03/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que reciba dos cadenas como parámetro (str1, str2) e imprima otras dos cadenas como salida (out1, out2). + * - out1 contendrá todos los caracteres presentes en la str1 pero NO estén presentes en str2. + * - out2 contendrá todos los caracteres presentes en la str2 pero NO estén presentes en str1. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + + +func printExclusiveChars(str1: String, str2: String) { + print("out1: \(str1.filter{ !str2.contains($0) })") + print("out2: \(str2.filter{ !str1.contains($0) })") + print() +} + +printExclusiveChars(str1: "Enunciado: Crea una función que reciba dos cadenas como parámetro (str1, str2) e imprima otras dos cadenas como salida (out1, out2).", + str2: "- out1 contendrá todos los caracteres presentes en la str1 pero NO estén presentes en str2.") +printExclusiveChars(str1: "Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada.", + str2: "Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación.") +printExclusiveChars(str1: "- out1 contendrá todos los caracteres presentes en la str1 pero NO estén presentes en str2.", + str2: "- out2 contendrá todos los caracteres presentes en la str2 pero NO estén presentes en str1.") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge11.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge11.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..666e6e9 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge11.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,45 @@ +import Foundation + +/* + * Reto #11 + * ELIMINANDO CARACTERES + * Fecha publicación enunciado: 14/03/22 + * Fecha publicación resolución: 21/03/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función en Swift que reciba dos cadenas como parámetro (str1, str2) e imprima otras dos cadenas como salida (out1, out2). + * - out1 contendrá todos los caracteres presentes en la str1 pero NO estén presentes en str2. + * - out2 contendrá todos los caracteres presentes en la str2 pero NO estén presentes en str1. + * + * Resuelto: Sí. En 2 iteracciones. + * Explicación: + * · Puedes usar la función filter() en conjunto con la propiedad contains() para crear la función que deseas. + * Conversación: + * - La salida con out1 y out2 debe imprimirla por pantalla directamente + * + En este caso, la función ya no devuelve una tupla con las dos cadenas de salida, sino que simplemente las imprime directamente en pantalla. + * Nota: falla en el comentario de su caso de prueba + * + */ + +func charactersNotInString(_ str1: String, _ str2: String) { + let out1 = String(str1.filter { !str2.contains($0) }) + let out2 = String(str2.filter { !str1.contains($0) }) + print(out1) + print(out2) +} + +charactersNotInString("hola", "mundo") // Imprime "ho" y "mu" en pantalla + +// Brais cases +charactersNotInString("brais","moure") // Esto imprimiría "out1: bais" y "out2: moue" +charactersNotInString("Me gusta Java","Me gusta Kotlin") // Esto imprimiría "out1: Jv" y "out2: Kolin" +charactersNotInString("Usa el canal de nuestro discord (https://mouredev.com/discord) \"🔁reto-semanal\" para preguntas, dudas o prestar ayuda a la comunidad.".lowercased(), + "Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada.".lowercased()) // Esto imprimiría "out1: (:///)"🔁-"" y "out2: fkqqó" + +// Jaime cases +charactersNotInString("Enunciado: Crea una función que reciba dos cadenas como parámetro (str1, str2) e imprima otras dos cadenas como salida (out1, out2).", + "- out1 contendrá todos los caracteres presentes en la str1 pero NO estén presentes en str2.") // Esto imprimiría "out1: Ei:Cfióqibmm(,)imimmi(,)" y "out2: -NOé" +charactersNotInString("Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada.", + "Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación.") // Esto imprimiría "out1: PFkyPqqm" y "out2: éjTwb" +charactersNotInString("- out1 contendrá todos los caracteres presentes en la str1 pero NO estén presentes en str2.", + "- out2 contendrá todos los caracteres presentes en la str2 pero NO estén presentes en str1.") // Esto imprimiría "out1: " y "out2: " (las cadenas vacías) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge12.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge12.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..28f4462 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge12.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,32 @@ +import Foundation + +/* + * Reto #12 + * ¿ES UN PALÍNDROMO? + * Fecha publicación enunciado: 21/03/22 + * Fecha publicación resolución: 28/03/22 + * Dificultad: MEDIA + * + * Enunciado: Escribe una función que reciba un texto y retorne verdadero o falso (Boolean) según sean o no palíndromos. + * Un Palíndromo es una palabra o expresión que es igual si se lee de izquierda a derecha que de derecha a izquierda. + * NO se tienen en cuenta los espacios, signos de puntuación y tildes. + * Ejemplo: Ana lleva al oso la avellana. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func isPalindrome(phrase: String) -> Bool { + var text = phrase.lowercased() + text = text.components(separatedBy: CharacterSet.punctuationCharacters).joined(separator: "") + text = text.components(separatedBy: " ").joined(separator: "") + text = text.folding(options: .diacriticInsensitive, locale: .current) + return text == String(text.reversed()) +} + +print(isPalindrome(phrase: "Ana lleva al oso la avellana.")) +print(isPalindrome(phrase: "Allí ves Sevilla")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge12.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge12.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..e1f64d7 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge12.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,42 @@ +import Foundation + +/* + * Reto #12 + * ¿ES UN PALÍNDROMO? + * Fecha publicación enunciado: 21/03/22 + * Fecha publicación resolución: 28/03/22 + * Dificultad: MEDIA + * + * Enunciado: Escribe una función en Swift que reciba un texto y retorne verdadero o falso (Boolean) según sean o no palíndromos. + * Un Palíndromo es una palabra o expresión que es igual si se lee de izquierda a derecha que de derecha a izquierda. + * NO se tienen en cuenta los espacios, signos de puntuación y tildes. + * Ejemplo: Ana lleva al oso la avellana. + * + * Resuelto: Sí + * Iteracciones: 1 + * Explicación: + * + */ + +func esPalindromo(_ texto: String) -> Bool { + // Convertimos el texto a minúsculas y eliminamos los espacios, signos de puntuación y tildes + let sinEspacios = texto.lowercased().replacingOccurrences(of: " ", with: "") + let sinSignos = sinEspacios.components(separatedBy: CharacterSet.punctuationCharacters) + .joined() + let sinTildes = sinSignos.folding(options: .diacriticInsensitive, locale: .current) + + // Invertimos el texto + let invertido = String(sinTildes.reversed()) + + // Devolvemos true si el texto original es igual al texto invertido + return sinTildes == invertido +} + +print(esPalindromo("Ana lleva al oso la avellana.")) // Imprime "true" + +// Brais cases +print(esPalindromo("Adivina ya te opina, ya ni miles origina, ya ni cetro me domina, ya ni monarcas, a repaso ni mulato carreta, acaso nicotina, ya ni cita vecino, anima cocina, pedazo gallina, cedazo terso nos retoza de canilla goza, de pánico camina, ónice vaticina, ya ni tocino saca, a terracota luminosa pera, sacra nómina y ánimo de mortecina, ya ni giros elimina, ya ni poeta, ya ni vida")) // Imprime "true" +print(esPalindromo("¿Qué os ha parecido el reto?")) // Imprime "false" + +// Jaime cases +print(esPalindromo("Allí ves Sevilla")) // Imprime "true" diff --git a/WeeklyChallenge2022.playground/Pages/Challenge13.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge13.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..f2088d6 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge13.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,29 @@ +import Foundation + +/* + * Reto #13 + * FACTORIAL RECURSIVO + * Fecha publicación enunciado: 28/03/22 + * Fecha publicación resolución: 04/04/22 + * Dificultad: FÁCIL + * + * Enunciado: Escribe una función que calcule y retorne el factorial de un número dado de forma recursiva. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func calculateFactorial(number: Int) -> Int { + if(number == 1) { + return 1 + } else { + return number * calculateFactorial(number: number-1) + } +} + +let number = 5 +print("\(number)! = \(calculateFactorial(number: number))") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge13.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge13.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..b020372 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge13.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,39 @@ +import Foundation + +/* + * Reto #13 + * FACTORIAL RECURSIVO + * Fecha publicación enunciado: 28/03/22 + * Fecha publicación resolución: 04/04/22 + * Dificultad: FÁCIL + * + * Enunciado: Escribe una función en Swift que calcule y retorne el factorial de un número dado de forma recursiva. + * + * Resuelto: Sí + * Iteracciones: 2 + * Explicación: La función recibe un entero n y retorna su factorial. Si el número dado es 0, el factorial es 1. Si el número es mayor que 0, se llama recursivamente a la función pasando como argumento n - 1 y se retorna el resultado de multiplicar n por el factorial de n - 1. + * Conversación: + * - Evita que falle si se le pasa un número entero negativo como parámetro + * + */ + +func factorial(n: Int) -> Int { + if n < 0 { + // Si n es un número entero negativo, se retorna -1 para indicar que no se puede calcular el factorial + return -1 + } else if n == 0 { + return 1 + } else { + return n * factorial(n: n - 1) + } +} + +// Brais cases +print(factorial(n: 0) == -1 ? "No tiene factorial" : factorial(n: 0)) // 1 +print(factorial(n: 7) == -1 ? "No tiene factorial" : factorial(n: 7)) // 5040 +print(factorial(n: 1) == -1 ? "No tiene factorial" : factorial(n: 1)) // 1 +print(factorial(n: -1) == -1 ? "No tiene factorial" : factorial(n: -1)) // No tiene factorial + +// Jaime case +let number = 5 +print("\(number)! = \(factorial(n: number))") // 120 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge14.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge14.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..ceda427 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge14.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,34 @@ +import Foundation + +/* + * Reto #14 + * ¿ES UN NÚMERO DE ARMSTRONG? + * Fecha publicación enunciado: 04/04/22 + * Fecha publicación resolución: 11/04/22 + * Dificultad: FÁCIL + * + * Enunciado: Escribe una función que calcule si un número dado es un número de Armstrong (o también llamado narcisista). + * Si no conoces qué es un número de Armstrong, debes buscar información al respecto. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func isArmstrong(number: Int) -> Bool { + var summatory = 0.0 + String(number).forEach { + summatory += pow(Double(String($0))!, Double(String(number).count)) + } + return Int(summatory) == number +} + +print(isArmstrong(number: 123)) +print(isArmstrong(number: 153)) +print(isArmstrong(number: 371)) +print(isArmstrong(number: 1080)) +print(isArmstrong(number: 1634)) +print(isArmstrong(number: 8208)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge14.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge14.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..4e28afb --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge14.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,66 @@ +import Foundation + +/* + * Reto #14 + * ¿ES UN NÚMERO DE ARMSTRONG? + * Fecha publicación enunciado: 04/04/22 + * Fecha publicación resolución: 11/04/22 + * Dificultad: FÁCIL + * + * Enunciado: Escribe una función en Swift que calcule si un número dado es un número de Armstrong (o también llamado narcisista). + * Si no conoces qué es un número de Armstrong, debes buscar información al respecto. + * + * Resuelto: Sí + * Iteracciones: 2 + * Explicación: Para calcular si un número es un número de Armstrong, necesitamos hacer lo siguiente: + · Separar cada dígito del número dado. + · Elevar cada dígito a la potencia del número de dígitos del número original. + · Sumar todas las potencias. + · Si la suma es igual al número original, entonces el número es un número de Armstrong. De lo contrario, no lo es. + * Conversación: + * - Con numeros negativos da error + * + */ + +func isArmstrongNumber(_ number: Int) -> Bool { + // Si el número es negativo, devolver falso + if number < 0 { + return false + } + + // Separar cada dígito del número + let digits = String(number).map { Int(String($0))! } + + // Elevar cada dígito a la potencia del número de dígitos + let poweredDigits = digits.map { pow(Double($0), Double(digits.count)) } + + // Sumar todas las potencias + let sum = poweredDigits.reduce(0, +) + + // Devolver si la suma es igual al número original + return sum == Double(number) +} + +print(isArmstrongNumber(153)) // true +print(isArmstrongNumber(371)) // true +print(isArmstrongNumber(9474)) // true +print(isArmstrongNumber(407)) // true +print(isArmstrongNumber(-153)) // false +print(isArmstrongNumber(-371)) // false +print(isArmstrongNumber(-9474)) // false +print(isArmstrongNumber(-407)) // false + +// Brais cases +print(isArmstrongNumber(371)) // Output: true +print(isArmstrongNumber(-371)) // Output: false +print(isArmstrongNumber(372)) // Output: false +print(isArmstrongNumber(0)) // Output: true + +// Jaime cases +print(isArmstrongNumber(123)) // Output: false +print(isArmstrongNumber(153)) // Output: true +print(isArmstrongNumber(371)) // Output: true +print(isArmstrongNumber(1080)) // Output: false +print(isArmstrongNumber(1634)) // Output: true +print(isArmstrongNumber(8208)) // Output: true + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge15.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge15.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..d3a97a5 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge15.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,41 @@ +import Foundation + +/* + * Reto #15 + * ¿CUÁNTOS DÍAS? + * Fecha publicación enunciado: 11/04/22 + * Fecha publicación resolución: 18/04/22 + * Dificultad: DIFÍCIL + * + * Enunciado: Crea una función que calcule y retorne cuántos días hay entre dos cadenas de texto que representen fechas. + * - Una cadena de texto que representa una fecha tiene el formato "dd/MM/yyyy". + * - La función recibirá dos String y retornará un Int. + * - La diferencia en días será absoluta (no importa el orden de las fechas). + * - Si una de las dos cadenas de texto no representa una fecha correcta se lanzará una excepción. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +private func daysInterval(dateText1: String, dateText2: String) -> Int { + let daySeconds = 60 * 60 * 24 + let formatter = DateFormatter() + formatter.dateFormat = "dd/MM/yyyy" + if let date1 = formatter.date(from: dateText1), let date2 = formatter.date(from: dateText2) { + return Int(abs(date1.timeIntervalSince(date2))) / daySeconds + } else { + print("Alguna de las dos fechas de entrada es errónea") + return -1 + } +} + +print(daysInterval(dateText1: "16/04/2022", dateText2: "16-04-2022")) // 0 +print(daysInterval(dateText1: "16/04/2022", dateText2: "16/13/2022")) // Alguna de las dos fechas de entrada es errónea +print(daysInterval(dateText1: "16/04/2022", dateText2: "32/04/2022")) // Alguna de las dos fechas de entrada es errónea +print(daysInterval(dateText1: "16/04/2022", dateText2: "17/04/2022")) // 1 +print(daysInterval(dateText1: "17/04/2022", dateText2: "16/04/2022")) // 1 +print(daysInterval(dateText1: "17/04/2022", dateText2: "16/04/2023")) // 364 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge15.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge15.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..202dfb8 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge15.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,95 @@ +import Foundation + +/* + * Reto #15 + * ¿CUÁNTOS DÍAS? + * Fecha publicación enunciado: 11/04/22 + * Fecha publicación resolución: 18/04/22 + * Dificultad: DIFÍCIL + * + * Enunciado: Crea una función en Swift que calcule y retorne cuántos días hay entre dos cadenas de texto que representen fechas. + * - Una cadena de texto que representa una fecha tiene el formato "dd/MM/yyyy". + * - La función recibirá dos String y retornará un Int. + * - La diferencia en días será absoluta (no importa el orden de las fechas). + * - Si una de las dos cadenas de texto no representa una fecha correcta se lanzará una excepción. + * + * Resuelto: Sí + * Iteracciones: 2 + * Explicación: Para resolver este problema, podemos crear una función que acepte dos cadenas de texto como parámetros y utilice el tipo DateFormatter de Swift para convertir estas cadenas en objetos Date. Luego, podemos calcular la diferencia entre estas dos fechas en días y retornar el resultado. + En este ejemplo, hemos creado una función daysBetween que acepta dos cadenas de texto como parámetros. Luego, creamos un objeto DateFormatter y configuramos su formato para que pueda interpretar correctamente las cadenas de texto como fechas. + A continuación, usamos el método date(from:) del objeto DateFormatter para convertir las dos cadenas de texto en objetos Date. Si alguna de las dos cadenas de texto no tiene un formato válido, el método date(from:) devolverá nil, por lo que podemos lanzar una excepción utilizando la sentencia throw. + Una vez que tenemos las dos fechas en forma de objetos Date, podemos calcular la diferencia entre ellas en días utilizando el objeto Calendar y el método dateComponents(_:from:to:). Este método nos permite obtener un conjunto de componentes de fecha (en este caso, solo necesitamos los días) entre dos fechas. + Finalmente, retornamos el valor absoluto de la diferencia en días, para que el resultado sea siempre positivo independientemente del orden en el que se hayan proporcionado las fechas. + * Conversación: + * - Ponme ejemplos de prueba donde se muestre el número de días o un texto si se ha lanzado el error + * + */ + +func daysBetween(date1: String, date2: String) throws -> Int { + let formatter = DateFormatter() + formatter.dateFormat = "dd/MM/yyyy" + + guard let dateA = formatter.date(from: date1), let dateB = formatter.date(from: date2) else { + throw NSError(domain: "Invalid date format", code: 0, userInfo: nil) + } + + let calendar = Calendar.current + let components = calendar.dateComponents([.day], from: dateA, to: dateB) + return abs(components.day!) +} + +do { + let days = try daysBetween(date1: "01/01/2022", date2: "01/01/2023") + print("Hay \(days) días entre las dos fechas") +} catch { + print("Error: \(error)") +} + +do { + let days = try daysBetween(date1: "01/01/2022", date2: "02/01/2022") + print("Hay \(days) días entre las dos fechas") +} catch { + print("Error: \(error)") +} + +do { + let days = try daysBetween(date1: "01/01/2022", date2: "31/12/2021") + print("Hay \(days) días entre las dos fechas") +} catch { + print("Error: \(error)") +} + +do { + let days = try daysBetween(date1: "01/01/2022", date2: "01/02/2022") + print("Hay \(days) días entre las dos fechas") +} catch { + print("Error: \(error)") +} + +do { + let days = try daysBetween(date1: "01/01/2022", date2: "01/01/2022") + print("Hay \(days) días entre las dos fechas") +} catch { + print("Error: \(error)") +} + +do { + let days = try daysBetween(date1: "01/01/2022", date2: "01/01/202") + print("Hay \(days) días entre las dos fechas") +} catch { + print("Error: \(error)") +} + +// Brais cases +do { print(try daysBetween(date1: "18/05/2022", date2: "29/05/2022")) } catch { print("Error en el formato de alguna fecha") } // 11 +do { print(try daysBetween(date1: "mouredev", date2: "29/04/2022")) } catch { print("Error en el formato de alguna fecha") } // Error en el formato de alguna fecha +do { print(try daysBetween(date1: "18/5/2022", date2: "29/04/2022")) } catch { print("Error en el formato de alguna fecha") } // Error en el formato de alguna fecha + +// Jaime cases +do { print(try daysBetween(date1: "16/04/2022", date2: "16-04-2022")) } catch { print("Error en el formato de alguna fecha") } // 0 +do { print(try daysBetween(date1: "16/04/2022", date2: "16/13/2022")) } catch { print("Error en el formato de alguna fecha") } // Error en el formato de alguna fecha +do { print(try daysBetween(date1: "16/04/2022", date2: "32/04/2022")) } catch { print("Error en el formato de alguna fecha") } // Error en el formato de alguna fecha +do { print(try daysBetween(date1: "16/04/2022", date2: "17/04/2022")) } catch { print("Error en el formato de alguna fecha") } // 1 +do { print(try daysBetween(date1: "17/04/2022", date2: "16/04/2022")) } catch { print("Error en el formato de alguna fecha") } // 1 +do { print(try daysBetween(date1: "17/04/2022", date2: "16/04/2023")) } catch { print("Error en el formato de alguna fecha") } // 364 + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge15.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge15.xcplaygroundpage/Contents.swift index 9e07a89..138a473 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge15.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Challenge15.xcplaygroundpage/Contents.swift @@ -54,6 +54,6 @@ func printDaysBetween(firstDate: String, secondDate: String) { } } -printDaysBetween(firstDate: "18/05/2022", secondDate: "29/05/2022") -printDaysBetween(firstDate: "mouredev", secondDate: "29/04/2022") -printDaysBetween(firstDate: "18/5/2022", secondDate: "29/04/2022") +printDaysBetween(firstDate: "18/05/2022", secondDate: "29/05/2022") // 0 +printDaysBetween(firstDate: "mouredev", secondDate: "29/04/2022") // Error en el formato de alguna fecha +printDaysBetween(firstDate: "18/5/2022", secondDate: "29/04/2022") // Error en el formato de alguna fecha diff --git a/WeeklyChallenge2022.playground/Pages/Challenge16.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge16.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..34320aa --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge16.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,44 @@ +import Foundation + +/* + * Reto #16 + * EN MAYÚSCULA + * Fecha publicación enunciado: 18/04/22 + * Fecha publicación resolución: 25/04/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que reciba un String de cualquier tipo y se encargue de + * poner en mayúscula la primera letra de cada palabra. + * - No se pueden utilizar operaciones del lenguaje que lo resuelvan directamente. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func capitalizeWords(text: String) -> String { + let wordSeparators = text.filter{ !$0.isLetter } + var result = "" + for charIndex in 0.. String { + let words = input.split(separator: " ") + let capitalizedWords = words.map { word in + var capitalizedWord = word + capitalizedWord.replaceSubrange(capitalizedWord.startIndex...capitalizedWord.startIndex, with: String(capitalizedWord[capitalizedWord.startIndex]).uppercased()) + return capitalizedWord + } + return capitalizedWords.joined(separator: " ") +} + +let input = "hello world" +let output = capitalizeWords(input: input) +print(output) // Imprime "Hello World" + +// Brais cases +print(capitalizeWords(input: "¿hola qué tal estás?")) +print(capitalizeWords(input: "¿hola qué tal estás?")) +print(capitalizeWords(input: "El niño ñoño")) + +// Jaime cases +print(capitalizeWords(input: "")) +print(capitalizeWords(input: "palabra")) +print(capitalizeWords(input: "varias palabras")) +print(capitalizeWords(input: "varias palabras, con puntuación.")) +print(capitalizeWords(input: "varias palabras, con puntuación y MAYÚSCULAS.")) +print(capitalizeWords(input: "varias palabras, con puntuación y MAYÚSCULAS\nen varias líneas.")) +print(capitalizeWords(input: "¡última hora! ¿hay novedades?")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge17.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge17.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..364fbf9 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge17.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,70 @@ +import Foundation + +/* + * Reto #17 + * LA CARRERA DE OBSTÁCULOS + * Fecha publicación enunciado: 25/04/22 + * Fecha publicación resolución: 02/05/22 + * Dificultad: MEDIA + * + * Enunciado: Crea una función que evalúe si un/a atleta ha superado correctamente una + * carrera de obstáculos. + * - La función recibirá dos parámetros: + * - Un array que sólo puede contener String con las palabras "run" o "jump" + * - Un String que represente la pista y sólo puede contener "_" (suelo) o "|" (valla) + * - La función imprimirá cómo ha finalizado la carrera: + * - Si el/a atleta hace "run" en "_" (suelo) y "jump" en "|" (valla) será correcto y no + * variará el símbolo de esa parte de la pista. + * - Si hace "jump" en "_" (suelo), se variará la pista por "x". + * - Si hace "run" en "|" (valla), se variará la pista por "/". + * - La función retornará un Boolean que indique si ha superado la carrera. + * Para ello tiene que realizar la opción correcta en cada tramo de la pista. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +enum AthleteState: String { + case jump + case run + + func getFail() -> Character { + switch(self) { + case .jump: return "/" + case .run: return "x" + } + } + + func getState() -> Character { + switch(self) { + case .jump: return "|" + case .run: return "_" + } + } +} + +func checkRace(athlete: [AthleteState], track: String) -> Bool { + var athleteTrack = Array(track) + if(athlete.count != track.count) { + return false + } + for segmentIndex in 0.. Int { +// return board.compactMap{ $0.filter{ $0 == self.rawValue }.count }.reduce(0,+) +// } +//} + +enum Player: String, CaseIterable { + case X + case O + func getTries(board: [[String]]) -> Int { + return board.compactMap{ $0.filter{ $0 == self.rawValue }.count }.reduce(0,+) + } +} + +func checkThreeInARow(board: [[String]]) -> String { + var result = "Nulo" + if((board.filter{ $0.count == 3 }.count == 3) && (abs(Player.X.getTries(board: board) - Player.O.getTries(board: board)) < 2)) { + result = "Empate" + if(Player.X.getTries(board: board) != Player.O.getTries(board: board)) { + Player.allCases.forEach { player in + if(board[0].filter{ $0 == player.rawValue }.count == 3) || (board[1].filter{ $0 == player.rawValue }.count == 3) || (board[2].filter{ $0 == player.rawValue }.count == 3) || (board.filter{ $0[0] == player.rawValue }.count == 3) || (board.filter{ $0[1] == player.rawValue }.count == 3) || (board.filter{ $0[2] == player.rawValue }.count == 3) || (board[0][0] == player.rawValue && board[1][1] == player.rawValue && board[2][2] == player.rawValue) || (board[0][2] == player.rawValue && board[1][1] == player.rawValue && board[2][0] == player.rawValue) { + result = player.rawValue + } + } + } + } + return result +} + + +print(checkThreeInARow(board: [["X","X","X"], + ["O",""], + ["","0","",""]])) + +print(checkThreeInARow(board: [["X","X","X"], + ["O","O","O"], + ["","",""]])) + +print(checkThreeInARow(board: [["X","X","X"], + ["O","O",""], + ["","",""]])) + +print(checkThreeInARow(board: [["O","O","O"], + ["O","X","X"], + ["O","X","X"]])) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge19.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge19.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..b1b8f20 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge19.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,25 @@ +import Foundation + +/* + * Reto #19 + * CONVERSOR TIEMPO + * Fecha publicación enunciado: 09/05/22 + * Fecha publicación resolución: 16/05/22 + * Dificultad: FACIL + * + * Enunciado: Crea una función que reciba días, horas, minutos y segundos (como enteros) y retorne su resultado en milisegundos. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func getMillis(days: Int, hours: Int, minutes: Int, seconds: Int) -> Int { + return (abs(days) * 86400 + abs(hours) * 3600 + abs(minutes) * 60 + abs(seconds)) * 1000 +} + +print(getMillis(days: -365, hours: 0, minutes: 0, seconds: 0)) +print(getMillis(days: 365, hours: 0, minutes: 0, seconds: 0)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge2.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge2.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..c47200a --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge2.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,28 @@ +import Foundation + +/* + * Reto #2 + * LA SUCESIÓN DE FIBONACCI + * Fecha publicación enunciado: 10/01/22 + * Fecha publicación resolución: 17/01/22 + * Dificultad: DIFÍCIL + * + * Enunciado: Escribe un programa que imprima los 50 primeros números de la sucesión de Fibonacci empezando en 0. + * La serie Fibonacci se compone por una sucesión de números en la que el siguiente siempre es la suma de los dos anteriores. + * 0, 1, 1, 2, 3, 5, 8, 13... + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ +var penultimate = 0 +var ultimate = 1 +(2...49).forEach { _ in + print("\(penultimate), ", terminator: "") + ultimate += penultimate + penultimate = ultimate - penultimate +} +print("\(penultimate), \(ultimate)") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge2.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge2.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..440b729 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge2.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,41 @@ +import Foundation + +/* + * Reto #2 + * LA SUCESIÓN DE FIBONACCI + * Fecha publicación enunciado: 10/01/22 + * Fecha publicación resolución: 17/01/22 + * Dificultad: DIFÍCIL + * + * Enunciado: Escribe un programa en Swift que imprima los 50 primeros números de la sucesión de Fibonacci empezando en 0. + * + * Resuelto: Sí + " Iteracciones: 2 + * Explicación: La sucesión de Fibonacci se define recursivamente. El primer número es 0 y el segundo es 1. A partir de ahí, cada número es la suma de los dos números anteriores. Por lo tanto, el tercer número es 0 + 1 = 1, el cuarto es 1 + 1 = 2, el quinto es 1 + 2 = 3, y así sucesivamente. + El código anterior utiliza una función fibonacci que implementa esta definición recursiva. Luego, usa un bucle for para imprimir los 50 primeros números de la sucesión. + * Conversación: + * - Funciona pero tarda bastante, ¿cómo sería de una forma más eficiente? + * - Ahora es mucho más rápido pero devuelve 51 valores + * Nota: explica el motivo de la mejora en eficiencia entre una versión y otra. + * + */ + +var memo: [Int: Int] = [:] + +func fibonacci(_ n: Int) -> Int { + if n == 0 { + return 0 + } else if n == 1 { + return 1 + } else if let value = memo[n] { + return value + } else { + let value = fibonacci(n - 1) + fibonacci(n - 2) + memo[n] = value + return value + } +} + +for i in 0...49 { + print(fibonacci(i)) +} diff --git a/WeeklyChallenge2022.playground/Pages/Challenge20.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge20.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..dc0d279 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge20.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,36 @@ +import Foundation +import SwiftUI + +/* + * Reto #20 + * PARANDO EL TIEMPO + * Fecha publicación enunciado: 16/05/22 + * Fecha publicación resolución: 23/05/22 + * Dificultad: MEDIA + * + * Enunciado: Crea una función que sume 2 números y retorne su resultado pasados unos segundos. + * - Recibirá por parámetros los 2 números a sumar y los segundos que debe tardar en finalizar su ejecución. + * - Si el lenguaje lo soporta, deberá retornar el resultado de forma asíncrona, es decir, sin detener la ejecución del programa principal. Se podría ejecutar varias veces al mismo tiempo. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func delayedAddition(num1: Int, num2: Int, seconds: Int, completion: @escaping ((Int) -> Void)) async throws { + DispatchQueue.main.asyncAfter(deadline: .now() + Double(seconds)) { + completion(num1 + num2) + } +} + +Task { + try await delayedAddition(num1: 10, num2: 30, seconds: 5) { result in + print(result) + } + try await delayedAddition(num1: 15, num2: 35, seconds: 6) { result in + print(result) + } +} diff --git a/WeeklyChallenge2022.playground/Pages/Challenge20.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge20.xcplaygroundpage/Contents.swift index 5e15f25..2253913 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge20.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Challenge20.xcplaygroundpage/Contents.swift @@ -1,4 +1,5 @@ import Foundation +import SwiftUI /* * Reto #20 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..d13327d --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,82 @@ +import Foundation + +/* + * Reto #21 + * CALCULADORA .TXT + * Fecha publicación enunciado: 23/05/22 + * Fecha publicación resolución: 01/06/22 + * Dificultad: MEDIA + * + * Enunciado: Lee el fichero "Challenge21.txt" incluido en el proyecto, calcula su resultado e imprímelo. + * - El .txt se corresponde con las entradas de una calculadora. + * - Cada línea tendrá un número o una operación representada por un símbolo (alternando ambos). + * - Soporta números enteros y decimales. + * - Soporta las operaciones suma "+", resta "-", multiplicación "*" y división "/". + * - El resultado se muestra al finalizar la lectura de la última línea (si el .txt es correcto). + * - Si el formato del .txt no es correcto, se indicará que no se han podido resolver las operaciones. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +enum Operation { + case add, div, mul, sub, error +} + +func isNumber(symbol: String?) -> Bool { + return symbol != nil && symbol!.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil +} + +func getOperation(symbol: String) -> Operation { + switch(symbol) { + case "+": return Operation.add + case "-": return Operation.sub + case "*": return Operation.mul + case "/": return Operation.div + default: return Operation.error + } +} + +func processOperations(fileName: String) -> String { + let BAD_RESPONSE = "Las operaciones no han podido ser resueltas." + do { + if let operationsFilePath = Bundle.main.path(forResource:fileName, ofType: "txt") { + let operationSymbols = try String(contentsOfFile: operationsFilePath, encoding: String.Encoding.utf8).components(separatedBy: "\n").dropLast() + if(isNumber(symbol: operationSymbols.first)) { + var result = Double(operationSymbols.first!)! + for index in stride(from: 1, to: operationSymbols.count, by: 2) { + if((getOperation(symbol: operationSymbols[index]) != Operation.error) && (index + 1 < operationSymbols.count) && isNumber(symbol: operationSymbols[index+1])) { + switch(getOperation(symbol: operationSymbols[index])) { + case .add: + result = result + Double(operationSymbols[index+1])! + case .div: + result = result / Double(operationSymbols[index+1])! + case .mul: + result = result * Double(operationSymbols[index+1])! + default: + result = result - Double(operationSymbols[index+1])! + } + } else { + return BAD_RESPONSE + } + } + return "\(result)" + } else { + return BAD_RESPONSE + } + } + return BAD_RESPONSE + } catch { + return BAD_RESPONSE + } +} + +print(processOperations(fileName: "Challenge21")) +print(processOperations(fileName: "OneValue")) +print(processOperations(fileName: "TooNumbers")) +print(processOperations(fileName: "TooOperators")) +print(processOperations(fileName: "WithDecimals")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/OneValue.txt b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/OneValue.txt new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/OneValue.txt @@ -0,0 +1 @@ +5 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/TooNumbers.txt b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/TooNumbers.txt new file mode 100644 index 0000000..b3502af --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/TooNumbers.txt @@ -0,0 +1,4 @@ +5 +2 ++ +3 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/TooOperators.txt b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/TooOperators.txt new file mode 100644 index 0000000..7413317 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/TooOperators.txt @@ -0,0 +1,6 @@ +5 ++ +2 +- +1 +* diff --git a/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/WithDecimals.txt b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/WithDecimals.txt new file mode 100644 index 0000000..33541ed --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge21.jaimefere.xcplaygroundpage/Resources/WithDecimals.txt @@ -0,0 +1,13 @@ +5.5 ++ +2.5 +- +1.5 +* +8.5 +- +15.5 ++ +4.5 +/ +2.5 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge21.xcplaygroundpage/Resources/Challenge21.txt b/WeeklyChallenge2022.playground/Pages/Challenge21.xcplaygroundpage/Resources/Challenge21.txt index d5b2bd7..f324e10 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge21.xcplaygroundpage/Resources/Challenge21.txt +++ b/WeeklyChallenge2022.playground/Pages/Challenge21.xcplaygroundpage/Resources/Challenge21.txt @@ -10,4 +10,4 @@ + 4 / -2 \ No newline at end of file +2 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge22.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge22.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..396a331 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge22.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,34 @@ +import Foundation + +/* + * Reto #22 + * CONJUNTOS + * Fecha publicación enunciado: 01/06/22 + * Fecha publicación resolución: 07/06/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que reciba dos array, un booleano y retorne un array. + * - Si el booleano es verdadero buscará y retornará los elementos comunes de los dos array. + * - Si el booleano es falso buscará y retornará los elementos no comunes de los dos array. + * - No se pueden utilizar operaciones del lenguaje que lo resuelvan directamente. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func findItems(array1: [AnyObject], array2: [AnyObject], commons: Bool) -> [AnyObject] { + if(commons) { + return array1.filter{ item in array2.contains(where: {$0 === item}) } + } else { + return array1.filter{ item in array2.filter{ $0 === item }.count == 0 } + array2.filter{ item in array1.filter{ $0 === item }.count == 0 } + } +} + +print("Elementos comunes: \(findItems(array1: ["manzana", "pera", "mango"] as [AnyObject], array2: ["manzana", "melón"] as [AnyObject], commons: true))") +print("Elementos distintos: \(findItems(array1: ["manzana", "pera", "mango"] as [AnyObject], array2: ["manzana", "melón"] as [AnyObject], commons: false))") +print("Elementos comunes: \(findItems(array1: [2, "pera", 5] as [AnyObject], array2: ["manzana", 5] as [AnyObject], commons: true))") +print("Elementos distintos: \(findItems(array1: [2, "pera", 5] as [AnyObject], array2: ["manzana", 5] as [AnyObject], commons: false))") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge23.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge23.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..e421e05 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge23.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,40 @@ +import Foundation + +/* + * Reto #23 + * MÁXIMO COMÚN DIVISOR Y MÍNIMO COMÚN MÚLTIPLO + * Fecha publicación enunciado: 07/06/22 + * Fecha publicación resolución: 13/06/22 + * Dificultad: MEDIA + * + * Enunciado: Crea dos funciones, una que calcule el máximo común divisor (MCD) y otra que calcule el mínimo común múltiplo (mcm) de dos números enteros. + * - No se pueden utilizar operaciones del lenguaje que lo resuelvan directamente. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + + +private func calculateMCD(n1: Int, n2: Int) -> Int { + for i in stride(from: min(n1, n2), to: 1, by: -1) { + if(n1 % i == 0 && n2 % i == 0) { + return i + } + } + return 1 +} + +private func calculateMCM(n1: Int, n2: Int) -> Int { + return n1 * n2 / calculateMCD(n1: n1, n2: n2) +} + +print(calculateMCD(n1: 6, n2: 9)) +print(calculateMCD(n1: 24, n2: 36)) +print(calculateMCD(n1: 8, n2: 8)) +print(calculateMCM(n1: 8, n2: 8)) +print(calculateMCM(n1: 51, n2: 27)) +print(calculateMCM(n1: 180, n2: 324)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge24.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge24.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..8063647 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge24.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,51 @@ +import Foundation + +/* + * Reto #24 + * ITERATION MASTER + * Fecha publicación enunciado: 13/06/22 + * Fecha publicación resolución: 20/06/22 + * Dificultad: FÁCIL + * + * Enunciado: Quiero contar del 1 al 100 de uno en uno (imprimiendo cada uno). ¿De cuántas maneras eres capaz de hacerlo? Crea el código para cada una de ellas. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +private func oneHundredFor() { + for i in 1...100 { + print(i) + } +} + +private func oneHundredForEach() { + (1...100).forEach { i in + print(i) + } +} + +private func oneHundredWhile() { + var i = 1 + while(i<=100) { + print(i) + i += 1 + } +} + +private func oneHundredDoWhile() { + var i = 0 + repeat { + i += 1 + print(i) + } while(i<100) +} + +oneHundredFor() +oneHundredForEach() +oneHundredWhile() +oneHundredDoWhile() diff --git a/WeeklyChallenge2022.playground/Pages/Challenge25.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge25.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..dbcb0d2 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge25.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,45 @@ +import Foundation + +/* + * Reto #25 + * PIEDRA, PAPEL, TIJERA + * Fecha publicación enunciado: 20/06/22 + * Fecha publicación resolución: 27/06/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa que calcule quien gana más partidas al piedra, papel, tijera. + * - El resultado puede ser: "Player 1", "Player 2", "Tie" (empate) + * - La función recibe un listado que contiene pares, representando cada jugada. + * - El par puede contener combinaciones de "R" (piedra), "P" (papel) o "S" (tijera). + * - Ejemplo. Entrada: [("R","S"), ("S","R"), ("P","S")]. Resultado: "Player 2". + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +enum Move { + case ROCK, PAPER, SCISSOR +} + +func playRockPaperScissor(moves: [(first: Move, second: Move)]) -> String { + var playerOneWins = 0 + var playerTwoWins = 0 + + moves.forEach { move in + if(move.first != move.second) { + if((move.first == Move.SCISSOR && move.second == Move.PAPER) || (move.first == Move.PAPER && move.second == Move.ROCK) || (move.first == Move.ROCK && move.second == Move.SCISSOR)) { + playerOneWins += 1 + } else { + playerTwoWins += 1 + } + } + } + return playerOneWins == playerTwoWins ? "Tie" : playerOneWins > playerTwoWins ? "Player 1" : "Player 2" +} + +print(playRockPaperScissor(moves: [(Move.ROCK, Move.SCISSOR), (Move.SCISSOR, Move.ROCK), (Move.PAPER, Move.SCISSOR)])) +print(playRockPaperScissor(moves: [(Move.ROCK, Move.ROCK), (Move.SCISSOR, Move.SCISSOR), (Move.PAPER, Move.PAPER)])) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge26.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge26.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..aca0fc7 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge26.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,49 @@ +import Foundation + +/* + * Reto #26 + * CUADRADO Y TRIÁNGULO 2D + * Fecha publicación enunciado: 27/06/22 + * Fecha publicación resolución: 07/07/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea un programa que dibuje un cuadrado o un triángulo con asteriscos "*". + * - Indicaremos el tamaño del lado y si la figura a dibujar es una u otra. + * - EXTRA: ¿Eres capaz de dibujar más figuras? + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + + +private enum Figure { + case SQUARE + case TRIANGLE +} + +private func drawPolygon(side: Int, figure: Figure) { + if(side < 2) { + print("La figura debe tener al menos 2 de lado\n") + } else { + (1...side).forEach { row in + var rowLine = "" + (1...side).forEach { column in + if(figure == Figure.SQUARE || column <= row) { + rowLine += "* " + } + } + print(rowLine) + } + print() + } +} + +drawPolygon(side: 1, figure: Figure.SQUARE) +drawPolygon(side: 2, figure: Figure.SQUARE) +drawPolygon(side: 2, figure: Figure.TRIANGLE) +drawPolygon(side: 5, figure: Figure.SQUARE) +drawPolygon(side: 5, figure: Figure.TRIANGLE) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge26.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge26.xcplaygroundpage/Contents.swift index ac5465c..b3b821a 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge26.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Challenge26.xcplaygroundpage/Contents.swift @@ -46,7 +46,9 @@ func drawPolygon(size: Int, type: PolygonType) { } else { print("\(String(repeating: " ", count: value - size))\(String(repeating: "* ", count: totalSize - value))") } + print(rowLine) } + print() } print("") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge27.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge27.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..b0a98b4 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge27.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,27 @@ +/* + * Reto #27 + * VECTORES ORTOGONALES + * Fecha publicación enunciado: 07/07/22 + * Fecha publicación resolución: 11/07/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea un programa que determine si dos vectores son ortogonales. + * - Los dos array deben tener la misma longitud. + * - Cada vector se podría representar como un array. Ejemplo: [1, -2] + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +private func areOrthogonals(vectorA: [Int], vectorB: [Int]) -> Bool { + return vectorA.count != 2 || vectorB.count != 2 ? false : vectorA[0] * vectorB[0] + vectorA[1] * vectorB[1] == 0 +} + +print(areOrthogonals(vectorA: [-1, 2], vectorB: [2, 1])) +print(areOrthogonals(vectorA: [2, 3], vectorB: [3, 2])) +print(areOrthogonals(vectorA: [], vectorB: [3, 2])) +print(areOrthogonals(vectorA: [1, 2, 3], vectorB: [3, 2])) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge28.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge28.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..fea2029 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge28.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,87 @@ +import Foundation + +/* + * Reto #28 + * MÁQUINA EXPENDEDORA + * Fecha publicación enunciado: 11/07/22 + * Fecha publicación resolución: 18/07/22 + * Dificultad: MEDIA + * + * Enunciado: Simula el funcionamiento de una máquina expendedora creando una operación + * que reciba dinero (array de monedas) y un número que indique la selección del producto. + * - El programa retornará el nombre del producto y un array con el dinero de vuelta (con el menor número de monedas). + * - Si el dinero es insuficiente o el número de producto no existe, deberá indicarse con un mensaje y retornar todas las monedas. + * - Si no hay dinero de vuelta, el array se retornará vacío. + * - Para que resulte más simple, trabajaremos en céntimos con monedas de 5, 10, 50, 100 y 200. + * - Debemos controlar que las monedas enviadas estén dentro de las soportadas. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +enum Coin: Int, CaseIterable, Comparable { + case five = 5 + case ten = 10 + case fifty = 50 + case oneHundred = 100 + case twoHundred = 200 + + static func < (lhs: Coin, rhs: Coin) -> Bool { + return lhs.rawValue < rhs.rawValue + } +} + +struct Product { + var name: String + var number: Int + var value: Int + + init(name: String, number: Int, value: Int) { + self.name = name + self.number = number + self.value = value + } +} + +func getExchange(value: Int) -> [Coin] { + var rest = value + var result: [Coin] = [] + repeat { + let biggestCoin = Coin.allCases.filter{ $0.rawValue <= rest }.sorted().last! + rest = rest - biggestCoin.rawValue + result.append(biggestCoin) + } while(rest > 0) + return result +} + +func getProduct(productNumber: Int, money: [Coin]) -> (productName: String, exchange: [Coin]) { + let machineProducts = [ + Product.init(name: "Estrella Galicia", number: 1, value: 120), + Product.init(name: "Alhambra Lager Singular", number: 2, value: 120), + Product.init(name: "Estrella Galicia 1906", number: 3, value: 180), + Product.init(name: "Alhambra Reserva 1900", number: 4, value: 180), + Product.init(name: "Heineken", number: 5, value: 20) + ] + + let selectedProducts = machineProducts.filter{ $0.number == productNumber} + if(selectedProducts.count == 0) { + print("Ningún producto tiene el identificador \(productNumber)") + return ("", money) + } else if(selectedProducts[0].value > money.compactMap{ $0.rawValue }.reduce(0,+)) { + print("Saldo insuficiente") + return ("", money) + } else { + return (selectedProducts[0].name, getExchange(value: money.compactMap{ $0.rawValue }.reduce(0,+) - selectedProducts[0].value)) + } +} + +var product = getProduct(productNumber: 7, money: [Coin.fifty]) +print(product.productName.isEmpty ? "" : "Producto: \(product.productName) - monedas: \(product.exchange.compactMap{ $0.rawValue })") +product = getProduct(productNumber: 1, money: [Coin.fifty, Coin.fifty]) +print(product.productName.isEmpty ? "" : "Producto: \(product.productName) - monedas: \(product.exchange.compactMap{ $0.rawValue })") +product = getProduct(productNumber: 2, money: [Coin.twoHundred]) +print(product.productName.isEmpty ? "" : "Producto: \(product.productName) - monedas: \(product.exchange.compactMap{ $0.rawValue })") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge29.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge29.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..6379689 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge29.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,98 @@ +import Foundation + +/* + * Reto #29 + * ORDENA LA LISTA + * Fecha publicación enunciado: 18/07/22 + * Fecha publicación resolución: 26/07/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que ordene y retorne una matriz de números. + * - La función recibirá un listado (por ejemplo [2, 4, 6, 8, 9]) y un parámetro adicional + * "Asc" o "Desc" para indicar si debe ordenarse de menor a mayor o de mayor a menor. + * - No se pueden utilizar funciones propias del lenguaje que lo resuelvan automáticamente. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func quickSort(numbers: [Int], first: Int = 0, last: Int) -> [Int] { + let p = numbers[(first + last) / 2] + var i = first + var j = last + var result = numbers + + repeat { + while(result[i] < p) { i += 1 } + while(p < result[j]) { j -= 1 } + if(i <= j) { + let aux = result[i] + result[i] = result[j] + result[j] = aux + i += 1 + j -= 1 + } + } while(i <= j) + if(first < j) { + result = quickSort(numbers: result, first: first, last: j) + } + if(i < last) { + result = quickSort(numbers: result, first: i, last: last) + } + + return result +} + +func bubbleSort(numbers: [Int]) -> [Int] { + var result = numbers + + (1...result.count-1).forEach { _ in + (0.. result[i+1]) { + let aux = result[i] + result[i] = result[i+1] + result[i+1] = aux + } + } + } + + return result +} + +func insertionSort(numbers: [Int]) -> [Int] { + var result = numbers + + (1..= 0 && result[j] > aux) { + result[j+1] = result[j] + j -= 1 + result[j+1] = aux + } + } + + return result +} + +func sortNumbers(numbers: [Int], order: String) { + if(order == "Asc") { + print("Quicksort: \(quickSort(numbers: numbers, last: numbers.count - 1))") + print("Bubble: \(bubbleSort(numbers: numbers))") + print("Insertion: \(insertionSort(numbers: numbers))") + print() + } else { + print("Quicksort: \(Array(quickSort(numbers: numbers, last: numbers.count - 1).reversed()))") + print("Bubble: \(Array(bubbleSort(numbers: numbers).reversed()))") + print("Insertion: \(Array(insertionSort(numbers: numbers).reversed()))") + print() + } +} + +sortNumbers(numbers: [8, 4, 2, 9, 1], order: "Asc") +sortNumbers(numbers: [9, 8, 0, 2, 5, 1, 3, 2, 9], order: "Desc") +sortNumbers(numbers: [3, 10, 1, 8, 15, 5, 12, 6, 5, 4], order: "Asc") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge3.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge3.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..45c9a45 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge3.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,39 @@ +import Foundation + +/* + * Reto #3 + * ¿ES UN NÚMERO PRIMO? + * Fecha publicación enunciado: 17/01/22 + * Fecha publicación resolución: 24/01/22 + * Dificultad: MEDIA + * + * Enunciado: Escribe un programa que se encargue de comprobar si un número es o no primo. + * Hecho esto, imprime los números primos entre 1 y 100. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func isPrime(_ number: Int) -> Bool { + if(number < 2) { + return false + } else { + var result = true + (2.. Bool { + if num <= 1 { + return false + } + + for i in 2.. Int? { + if(numbers.count < 2) { + print("¡El listado debe contener al menos 2 números!") + return nil + } else { + var biggest = numbers[0] + var result = numbers[0] + numbers.forEach { + if($0 > biggest) { + result = biggest + biggest = $0 + } + } + return result + } +} + +print(getTheBigestTwo(numbers: []) ?? "") +print(getTheBigestTwo(numbers: [4]) ?? "") +print(getTheBigestTwo(numbers: [4, 4]) ?? "") +print(getTheBigestTwo(numbers: [4, 6, 1, 8, 2]) ?? "") + + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge33.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge33.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..fa7d717 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge33.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,67 @@ +import Foundation + +/* + * Reto #33 + * CICLO SEXAGENARIO CHINO + * Fecha publicación enunciado: 15/08/22 + * Fecha publicación resolución: 22/08/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un función, que dado un año, indique el elemento y animal correspondiente + * en el ciclo sexagenario del zodíaco chino. + * - Información: https://www.travelchinaguide.com/intro/astrology/60year-cycle.htm + * - El ciclo sexagenario se corresponde con la combinación de los elementos madera, + * fuego, tierra, metal, agua y los animales rata, buey, tigre, conejo, dragón, serpiente, + * caballo, oveja, mono, gallo, perro, cerdo (en este orden). + * - Cada elemento se repite dos años seguidos. + * - El último ciclo sexagenario comenzó en 1984 (Madera Rata). + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en https://retosdeprogramacion.com/semanales2022. + * + */ + +enum Animal: Int, CaseIterable { + case rat = 0 + case ox = 1 + case tiger = 2 + case rabbit = 3 + case dragon = 4 + case snake = 5 + case horse = 6 + case sheep = 7 + case monkey = 8 + case roaster = 9 + case dog = 10 + case pig = 11 +} + +enum Element: Int, CaseIterable { + case wood = 0 + case fire = 2 + case earth = 4 + case metal = 6 + case water = 8 +} + +func getAnimalBy(sexagenarianCycleIndex: Int) -> Animal { + return Animal.allCases.first{ $0.rawValue == (sexagenarianCycleIndex % Animal.allCases.count) }! +} + +func getElementBy(sexagenarianCycleIndex: Int) -> Element { + return Element.allCases.first{ $0.rawValue == (sexagenarianCycleIndex % (Element.allCases.count * 2)) || $0.rawValue + 1 == (sexagenarianCycleIndex % (Element.allCases.count * 2)) }! +} + +func getChineseZodiacSymbolsBy(year: Int) -> String { + if(year < 604) { + return "El zodiaco chino comenzó más tarde, en el año 604 d.c." + } + let sexagenarianCycleIndex = year - 604 + return "Para el año \(year) el animal es \(getAnimalBy(sexagenarianCycleIndex: sexagenarianCycleIndex)) y el elemento es \(getElementBy(sexagenarianCycleIndex: sexagenarianCycleIndex))" +} + +print(getChineseZodiacSymbolsBy(year: 1924)) +print(getChineseZodiacSymbolsBy(year: 1940)) +print(getChineseZodiacSymbolsBy(year: 1969)) +print(getChineseZodiacSymbolsBy(year: 1983)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge34.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge34.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..988f8c8 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge34.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,65 @@ +import Foundation + +/* + * Reto #34 + * LOS NÚMEROS PERDIDOS + * Fecha publicación enunciado: 22/08/22 + * Fecha publicación resolución: 29/08/22 + * Dificultad: FÁCIL + * + * Enunciado: Dado un array de enteros ordenado y sin repetidos, crea una función que calcule y retorne todos los que faltan entre el mayor y el menor. + * - Lanza un error si el array de entrada no es correcto. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en https://retosdeprogramacion.com/semanales2022. + * + */ + +enum WrongArrayError: Error { + case empty + case nonUniqueValues + case unsorted +} + +func getMissedValues(numbers: Array) throws -> Array { + var missedValues: Array = [] + if(numbers.isEmpty) { + throw WrongArrayError.empty + } + var index = 0 + try numbers.sorted().forEach { number in + if(number != numbers[index]) { + throw WrongArrayError.unsorted + } + index += 1 + } + if(Array(Set(numbers)).count != numbers.count) { + throw WrongArrayError.nonUniqueValues + } + (0...(numbers.last! - numbers.first!)).forEach { index in + if(!numbers.contains(index + numbers.first!)) { + missedValues.append(index + numbers.first!) + } + } + return missedValues +} + +func printMissedValues(numbers: Array) { + do { + print(try getMissedValues(numbers: numbers)) + } catch WrongArrayError.unsorted { + print("El array no es válido porque los elementos no están correctamente ordenados") + } catch WrongArrayError.nonUniqueValues { + print("El array no es válido porque tiene elementos repetidos") + } catch { + print("El array está vacío") + } +} + +printMissedValues(numbers: [5,5,6,7,8]) +printMissedValues(numbers: [8,7,6,5]) +printMissedValues(numbers: []) +printMissedValues(numbers: [5]) +printMissedValues(numbers: [5,6,7,8]) +printMissedValues(numbers: [5,8]) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge35.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge35.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..ed85b4d --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge35.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,72 @@ +import Foundation + +/* + * Reto #35 + * BATALLA POKÉMON + * Fecha publicación enunciado: 29/08/22 + * Fecha publicación resolución: 06/09/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa que calcule el daño de un ataque durante una batalla Pokémon. + * - La fórmula será la siguiente: daño = 50 * (ataque / defensa) * efectividad + * - Efectividad: x2 (súper efectivo), x1 (neutral), x0.5 (no es muy efectivo) + * - Sólo hay 4 tipos de Pokémon: Agua, Fuego, Planta y Eléctrico (buscar su efectividad) + * - El programa recibe los siguientes parámetros: + * - Tipo del Pokémon atacante. + * - Tipo del Pokémon defensor. + * - Ataque: Entre 1 y 100. + * - Defensa: Entre 1 y 100. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +enum PokemonType { + case electric + case fire + case plant + case water + + func getEffectivity(opponent: PokemonType) -> Double { + switch(self) { + case .electric: switch(opponent) { + case .electric: return 0.5 + case .fire: return 1.0 + case .plant: return 0.5 + case .water: return 2.0 + } + case .fire: switch(opponent) { + case .electric: return 1.0 + case .fire: return 0.5 + case .plant: return 2.0 + case .water: return 0.5 + } + case .plant: switch(opponent) { + case .electric: return 1.0 + case .fire: return 0.5 + case .plant: return 0.5 + case .water: return 2.0 + } + case .water: switch(opponent) { + case .electric: return 1.0 + case .fire: return 2.0 + case .plant: return 0.5 + case .water: return 0.5 + } + } + } +} + +func getAttackDamage(attacker: PokemonType, defender: PokemonType, attack: Int, defence: Int) -> String { + if(attack < 1 || attack > 100) || (defence < 1 || defence > 100) { + return (attack < 1 || attack > 100) ? "El ataque no tiene un valor correcto" : "La defensa no tiene un valor correcto" + } else { + return "El daño de la pelea es \(50.0 * (Double(attack) / Double(defence)) * attacker.getEffectivity(opponent: defender))" + } +} + +print(getAttackDamage(attacker: PokemonType.fire, defender: PokemonType.plant, attack: 30, defence: 60)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge36.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge36.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..76cc04a --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge36.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,66 @@ +import Foundation + +/* + * Reto #36 + * LOS ANILLOS DE PODER + * Fecha publicación enunciado: 06/09/22 + * Fecha publicación resolución: 14/09/22 + * Dificultad: MEDIA + * + * Enunciado: ¡La Tierra Media está en guerra! En ella lucharán razas leales a Sauron + * contra otras bondadosas que no quieren que el mal reine sobre sus tierras. + * Cada raza tiene asociado un "valor" entre 1 y 5: + * - Razas bondadosas: Pelosos (1), Sureños buenos (2), Enanos (3), Númenóreanos (4), Elfos (5) + * - Razas malvadas: Sureños malos (2), Orcos (2), Goblins (2), Huargos (3), Trolls (5) + * Crea un programa que calcule el resultado de la batalla entre los 2 tipos de ejércitos: + * - El resultado puede ser que gane el bien, el mal, o exista un empate. Dependiendo de la + * suma del valor del ejército y el número de integrantes. + * - Cada ejército puede estar compuesto por un número de integrantes variable de cada raza. + * - Tienes total libertad para modelar los datos del ejercicio. + * Ej: 1 Peloso pierde contra 1 Orco, 2 Pelosos empatan contra 1 Orco, 3 Pelosos ganan a 1 Orco. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +enum BattleResult { + case draw, evil, good +} + +enum GoodRace: Int { + case Pelosos = 1 + case SureñosBuenos = 2 + case Enanos = 3 + case Numenoreanos = 4 + case Elfos = 5 + + func strength() -> Int { + return self.rawValue + } +} + +enum EvilRace { + case SureñosMalos, Orcos, Goblins, Huargos, Trolls + + func strength() -> Int { + switch(self) { + case .SureñosMalos, .Orcos, .Goblins: return 2 + case .Huargos: return 3 + case .Trolls: return 5 + } + } +} + +func battle(goodArmy: [GoodRace : Int], evilArmy: [EvilRace : Int]) -> BattleResult { + let goodStrength = goodArmy.map({ $0.key.strength() * $0.value }).reduce(0, +) + let evilStrength = evilArmy.map({ $0.key.strength() * $0.value }).reduce(0, +) + return goodStrength == evilStrength ? .draw : (goodStrength > evilStrength ? .good : .evil) +} + +print(battle(goodArmy: [.Pelosos: 1], evilArmy: [.Orcos:1])) +print(battle(goodArmy: [.Pelosos: 2], evilArmy: [.Orcos:1])) +print(battle(goodArmy: [.Pelosos: 3], evilArmy: [.Orcos:1])) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge37.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge37.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..de6eb77 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge37.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,117 @@ +import Foundation + +/* + * Reto #37 + * LOS LANZAMIENTOS DE "THE LEGEND OF ZELDA" + * Fecha publicación enunciado: 14/09/22 + * Fecha publicación resolución: 19/09/22 + * Dificultad: MEDIA + * + * Enunciado: ¡Han anunciado un nuevo "The Legend of Zelda"! Se llamará "Tears of the Kingdom" + * y se lanzará el 12 de mayo de 2023. + * Pero, ¿recuerdas cuánto tiempo ha pasado entre los distintos "The Legend of Zelda" de la historia? + * Crea un programa que calcule cuántos años y días hay entre 2 juegos de Zelda que tú selecciones. + * - Debes buscar cada uno de los títulos y su día de lanzamiento (si no encuentras el día exacto + * puedes usar el mes, o incluso inventártelo) + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +enum ZeldaEdition { + case TheLegendOfZelda + case TheAdventureOfLink + case ALinkToThePast + case LinksAwakenings + case OcarinaOfTime + case MejorasMask + case OracleOfSeasons + case OracleOfAges + case ALinkToThePastAndFourSwords + case TheWindWaker + case FourSwordsAdventures + case TheMinishCap + case TwilightPrincess + case PhantomHourglass + case SpiritTracks + case SkywordSword + case ALinkBetweenWords + case TriForceHeroes + case BreathOfTheWild + case TearsOfTheKingdom + + var releaseDate: String { + switch self { + case .TheLegendOfZelda: return "21/02/1986" + case .TheAdventureOfLink: return "14/01/1987" + case .ALinkToThePast: return "21/11/1991" + case .LinksAwakenings: return "06/06/1993" + case .OcarinaOfTime: return "21/11/1998" + case .MejorasMask: return "27/04/2000" + case .OracleOfSeasons: return "27/02/2001" + case .OracleOfAges: return "27/02/2001" + case .ALinkToThePastAndFourSwords: return "03/12/2002" + case .TheWindWaker: return "03/12/2002" + case .FourSwordsAdventures: return "18/03/2004" + case .TheMinishCap: return "04/11/2004" + case .TwilightPrincess: return "19/11/2006" + case .PhantomHourglass: return "23/06/2007" + case .SpiritTracks: return "07/12/2009" + case .SkywordSword: return "18/11/2011" + case .ALinkBetweenWords: return "22/11/2013" + case .TriForceHeroes: return "22/11/2015" + case .BreathOfTheWild: return "03/03/2017" + case .TearsOfTheKingdom: return "12/05/2023" + } + } + + var name: String { + switch self { + case .TheLegendOfZelda: return "The Legend of Zelda" + case .TheAdventureOfLink: return "The Adventure of Link" + case .ALinkToThePast: return "A Link to the Past" + case .LinksAwakenings: return "Link's Awakening" + case .OcarinaOfTime: return "Ocarina of Time" + case .MejorasMask: return "Majora's Mask" + case .OracleOfSeasons: return "Oracle of Seasons" + case .OracleOfAges: return "Oracle of Ages" + case .ALinkToThePastAndFourSwords: return "A Link to the Past & Four Swords" + case .TheWindWaker: return "The Wind Waker" + case .FourSwordsAdventures: return "Four Swords Adventures" + case .TheMinishCap: return "The Minish Cap" + case .TwilightPrincess: return "Twilight Princess" + case .PhantomHourglass: return "Phantom Hourglass" + case .SpiritTracks: return "Spirit Tracks" + case .SkywordSword: return "Skyward Sword" + case .ALinkBetweenWords: return "A Link Between Worlds" + case .TriForceHeroes: return "Tri Force Heroes" + case .BreathOfTheWild: return "Breath of the Wild" + case .TearsOfTheKingdom: return "Tears of the Kingdom" + } + } +} + +// From Challenge 15 +private func daysInterval(dateText1: String, dateText2: String) -> Int { + let daySeconds = 60 * 60 * 24 + let formatter = DateFormatter() + formatter.dateFormat = "dd/MM/yyyy" + if let date1 = formatter.date(from: dateText1), let date2 = formatter.date(from: dateText2) { + return Int(abs(date1.timeIntervalSince(date2))) / daySeconds + } else { + print("Alguna de las dos fechas de entrada es errónea") + return -1 + } +} + +private func timeBetweenZeldaEditions(anEdition: ZeldaEdition, otherEdition: ZeldaEdition) -> String { + let days = daysInterval(dateText1: anEdition.releaseDate, dateText2: otherEdition.releaseDate) + let years = Int(ceil(Double(days) / 365.0)) + return "\(years) años y \(days % 365) días de diferencia entre el lanzamiento de '\(anEdition.name)' y '\(otherEdition.name)'" +} + +print(timeBetweenZeldaEditions(anEdition: ZeldaEdition.TheLegendOfZelda, otherEdition: ZeldaEdition.TearsOfTheKingdom)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge38.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge38.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..5fb5ad7 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge38.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,38 @@ +import Foundation + +/* + * Reto #38 + * BINARIO A DECIMAL + * Fecha publicación enunciado: 19/09/22 + * Fecha publicación resolución: 27/09/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa se encargue de transformar un número binario a decimal sin utilizar + * funciones propias del lenguaje que lo hagan directamente. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +func passToDecimal(binaryNumber: String) -> Int { + var result = 0.0 + var index = 0.0 + binaryNumber.reversed().forEach { c in + result += Double(c.description)! * pow(2.0, index) + index += 1.0 + } + return Int(result) +} + +let binaryNumbers = ["012", "01", "10", "10000000"] +binaryNumbers.forEach { binaryNumber in + if(binaryNumber.filter { $0 != "0" && $0 != "1" }.isEmpty ) { + print(passToDecimal(binaryNumber: binaryNumber)) + } else { + print("No es un número binario correcto") + } +} diff --git a/WeeklyChallenge2022.playground/Pages/Challenge39.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge39.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..ba443db --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge39.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,56 @@ +import Foundation + +/* + * Reto #39 + * TOP ALGORITMOS: QUICK SORT + * Fecha publicación enunciado: 27/09/22 + * Fecha publicación resolución: 03/10/22 + * Dificultad: MEDIA + * + * Enunciado: Implementa uno de los algoritmos de ordenación más famosos: el "Quick Sort", + * creado por C.A.R. Hoare. + * - Entender el funcionamiento de los algoritmos más utilizados de la historia nos ayuda a + * mejorar nuestro conocimiento sobre ingeniería de software. Dedícale tiempo a entenderlo, + * no únicamente a copiar su implementación. + * - Esta es una nueva serie de retos llamada "TOP ALGORITMOS", donde trabajaremos y entenderemos + * los más famosos de la historia. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +// Already implemented in challenge #29 +func quickSort(numbers: [Int], first: Int = 0, last: Int) -> [Int] { + let p = numbers[(first + last) / 2] + var i = first + var j = last + var result = numbers + + repeat { + while(result[i] < p) { i += 1 } + while(p < result[j]) { j -= 1 } + if(i <= j) { + let aux = result[i] + result[i] = result[j] + result[j] = aux + i += 1 + j -= 1 + } + } while(i <= j) + if(first < j) { + result = quickSort(numbers: result, first: first, last: j) + } + if(i < last) { + result = quickSort(numbers: result, first: i, last: last) + } + + return result +} + +let numbers = [3, 10, 1, 8, 15, 5, 12, 6, 5, 4] +print("Quicksort ASC: \(quickSort(numbers: numbers, last: numbers.count - 1))") +print("Quicksort DESC: \(Array(quickSort(numbers: numbers, last: numbers.count - 1).reversed()))") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge4.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge4.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..fa8890f --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge4.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,38 @@ +import Foundation + +/* + * Reto #4 + * ÁREA DE UN POLÍGONO + * Fecha publicación enunciado: 24/01/22 + * Fecha publicación resolución: 31/01/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea UNA ÚNICA FUNCIÓN en Swift (importante que sólo sea una) que sea capaz de calcular y retornar el área de un polígono. + * - La función recibirá por parámetro sólo UN polígono a la vez. + * - Los polígonos soportados serán Triángulo, Cuadrado y Rectángulo. + * - Imprime el cálculo del área de un polígono de cada tipo. + * + * Resuelto: Sí. + " Iteracciones: 2 + * Explicación: En este ejemplo, la función area recibe como parámetros una cadena que indica el tipo de polígono (triángulo, cuadrado o rectángulo) y dos números enteros que representan los lados del polígono. La función calcula y retorna el área del polígono, utilizando la fórmula correspondiente según el tipo de polígono que se le haya pasado. + * Conversación: + * - Los polígonos Cuadrado y Rectángulo tienen la misma fórmula, ¿podrían estar en el mismo case del switch? + * + */ + +func area(poligono: String, lado1: Int, lado2: Int) -> Int { + switch poligono { + case "triangulo": + return (lado1 * lado2) / 2 + case "cuadrado": + return lado1 * lado1 + case "rectangulo": + return lado1 * lado2 + default: + return 0 + } +} + +print(area(poligono: "triangulo", lado1: 5, lado2: 10)) // Imprime 25 +print(area(poligono: "cuadrado", lado1: 5, lado2: 0)) // Imprime 25 +print(area(poligono: "rectangulo", lado1: 5, lado2: 10)) // Imprime 50 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge4.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge4.xcplaygroundpage/Contents.swift index f3b4837..8eb0cb9 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge4.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Challenge4.xcplaygroundpage/Contents.swift @@ -73,3 +73,9 @@ func area(polygon: Polygon) -> Double { polygon.printArea() return polygon.area() } + +print(Polygon.init(hasFourVertices: true, sideA: 4).getArea()) +print(Polygon.init(hasFourVertices: true, sideA: 7, sideB: 4).getArea()) +print(Polygon.init(hasFourVertices: false, sideA: 3, sideB: 4, sideC: 5).getArea()) +print(Polygon.init(hasFourVertices: false, sideA: 3, sideB: 4).getArea()) // isosceles +print(Polygon.init(hasFourVertices: false, sideA: 3).getArea()) // equilateral diff --git a/WeeklyChallenge2022.playground/Pages/Challenge40.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge40.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..24733d3 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge40.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,52 @@ +import Foundation + +/* + * Reto #40 + * TRIÁNGULO DE PASCAL + * Fecha publicación enunciado: 03/10/22 + * Fecha publicación resolución: 10/10/22 + * Dificultad: MEDIA + * + * Enunciado: Crea una función que sea capaz de dibujar el "Triángulo de Pascal" indicándole + * únicamente el tamaño del lado. + * - Aquí puedes ver rápidamente cómo se calcula el triángulo: + * https://commons.wikimedia.org/wiki/File:PascalTriangleAnimated2.gif + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +private func printLine(line: [Int], tab: Int) { + var result = "" + (0...(tab * 2 + Int(round(Double(line.count) / 2.0)))).forEach { _ in + result = "\(result) " + } + line.forEach { i in + result += "\(i<10 ? " " : " ")\(i)" + } + print(result) +} + +private func drawPascalTriangle(side: Int) { + var previousLine = [1] + var row = 1 + (1.. String { + if(V == nil) { + return (R == nil || I == nil) ? "Invalid values" : String(format: " %.2f", R! * I!) + } else if(R == nil) { + return (V == nil || I == nil) ? "Invalid values" : String(format: " %.2f", V! / I!) + } else if(I == nil) { + return (V == nil || R == nil) ? "Invalid values" : String(format: " %.2f", V! / R!) + } else { + return (V! != R! * I!) ? "Invalid values" : "Right values" + } +} + +print(calculateOhmLayer(V: 5, R: 10, I: 0.5)) +print(calculateOhmLayer(V: nil, R: 10, I: 0.5)) +print(calculateOhmLayer(V: 5, R: nil, I: 0.5)) +print(calculateOhmLayer(V: 5, R: 10, I: nil)) +print(calculateOhmLayer(V: nil, R: nil, I: 0.5)) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge42.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge42.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..7c87be1 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge42.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,59 @@ +import Foundation + +/* + * Reto #42 + * CONVERSOR DE TEMPERATURA + * Fecha publicación enunciado: 17/10/22 + * Fecha publicación resolución: 24/10/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que transforme grados Celsius en Fahrenheit y viceversa. + * - Para que un dato de entrada sea correcto debe poseer un símbolo "°" y su unidad ("C" o "F"). + * - En caso contrario retornará un error. + * - ¿Quieres emplear lo aprendido en este reto? + * Revisa el reto mensual y crea una App: https://retosdeprogramacion.com/mensuales2022 + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +enum TemperatureUnit: String, CaseIterable { + case celsius = "C" + case fahrenheit = "F" + + static func isValid(unit: String) -> Bool { + return TemperatureUnit.allCases.filter{ $0.rawValue == unit }.count > 0 + } +} + +func isNumber(symbol: String?) -> Bool { + return symbol != nil && symbol!.rangeOfCharacter(from: CharacterSet.decimalDigits) != nil +} + +func toggleTemperatureUnits(temperature: String) -> String { + let temperatureParts = temperature.replacingOccurrences(of: " ", with: "").uppercased().split(separator: "º") + if(temperatureParts.count == 2 && isNumber(symbol: String(temperatureParts[0])) && TemperatureUnit.isValid(unit: String(temperatureParts[1]))) { + let value = Double(temperatureParts[0])! + let units = temperatureParts[1] + if(units == TemperatureUnit.celsius.rawValue) { + return "\(String(format: "%.2f", value * 9.0 / 5.0 + 32.0)) º\(TemperatureUnit.fahrenheit.rawValue)" + } else { + return "\(String(format: "%.2f", (value - 32.0) * 5.0 / 9.0)) º\(TemperatureUnit.celsius.rawValue)" + } + } else { + return "Incorrect input" + } +} + +print(toggleTemperatureUnits(temperature: "60 F")) +print(toggleTemperatureUnits(temperature: "ab ºC")) +print(toggleTemperatureUnits(temperature: "12 ºCF")) +print(toggleTemperatureUnits(temperature: "273.15ºC")) +print(toggleTemperatureUnits(temperature: "-40.0ºC")) +print(toggleTemperatureUnits(temperature: "0 ºC")) +print(toggleTemperatureUnits(temperature: "98.6ºF")) +print(toggleTemperatureUnits(temperature: "212ºF")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge43.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge43.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..f1061d1 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge43.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,94 @@ +import Foundation + +/* + * Reto #43 + * TRUCO O TRATO + * Fecha publicación enunciado: 24/10/22 + * Fecha publicación resolución: 02/11/22 + * Dificultad: MEDIA + * + * Enunciado: Este es un reto especial por Halloween. + * Deberemos crear un programa al que le indiquemos si queremos realizar "Truco o Trato" y + * un listado (array) de personas con las siguientes propiedades: + * - Nombre de la niña o niño + * - Edad + * - Altura en centímetros + * + * Si las personas han pedido truco, el programa retornará sustos (aleatorios) + * siguiendo estos criterios: + * - Un susto por cada 2 letras del nombre por persona + * - Dos sustos por cada edad que sea un número par + * - Tres sustos por cada 100 cm de altura entre todas las personas + * - Sustos: 🎃 👻 💀 🕷 🕸 🦇 + * + * Si las personas han pedido trato, el programa retornará dulces (aleatorios) + * siguiendo estos criterios: + * - Un dulce por cada letra de nombre + * - Un dulce por cada 3 años cumplidos hasta un máximo de 10 años por persona + * - Dos dulces por cada 50 cm de altura hasta un máximo de 150 cm por persona + * - Dulces: 🍰 🍬 🍡 🍭 🍪 🍫 🧁 🍩 + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +enum HalloweenAction { + case trick + case treat +} + +private struct Child { + let name: String + let age, height: Int +} + +private func showScares(counter: Int) -> String { + let scares = ["🎃", "👻", "💀", "🕷", "🕸", "🦇"] + var result = "" + (0.. String { + let sweets = ["🍰", "🍬", "🍡", "🍭", "🍪", "🍫", "🧁", "🍩"] + var result = "" + (0.., halloweenAction: HalloweenAction) { + var result = "" + if(halloweenAction == HalloweenAction.trick) { + var totalHeight = 0 + children.forEach { child in + result += showScares(counter: child.name.count / 2) // 11 + if(child.age % 2 == 0){ result += showScares(counter: 2) } // 4 + totalHeight += child.height + } + result += showScares(counter: (totalHeight / 100) * 3) // 15 + } else { + children.forEach { child in + result += showSweets(counter: child.name.count) // 23 + result += showSweets(counter: min(child.age, 10) / 3) // 11 + result += showSweets(counter: min(child.height, 150) / 50 * 2) // 18 + } + } + print(result) +} + +trickOrTreat(children: [Child(name: "Juan", age: 9, height: 140), + Child(name: "Arturo", age: 11, height: 121), + Child(name: "Rodrigo", age: 8, height: 162), + Child(name: "Javier", age: 12, height: 136)], halloweenAction: HalloweenAction.trick) +trickOrTreat(children: [Child(name: "Juan", age: 9, height: 140), + Child(name: "Arturo", age: 11, height: 121), + Child(name: "Rodrigo", age: 8, height: 162), + Child(name: "Javier", age: 12, height: 136)], halloweenAction: HalloweenAction.treat) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge44.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge44.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..b080d4c --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge44.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,38 @@ +import Foundation + +/* + * Reto #44 + * BUMERANES + * Fecha publicación enunciado: 02/10/22 + * Fecha publicación resolución: 07/11/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que retorne el número total de bumeranes de un array de números + * enteros e imprima cada uno de ellos. + * - Un bumerán (búmeran, boomerang) es una secuencia formada por 3 números seguidos, en el que el + * primero y el último son iguales, y el segundo es diferente. Por ejemplo [2, 1, 2]. + * - En el array [2, 1, 2, 3, 3, 4, 2, 4] hay 2 bumeranes ([2, 1, 2] y [4, 2, 4]). + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +func getNumOfBoomerangs(numbers: [Int]) -> Int { + var numOfBoomerangs = 0 + if(numbers.count >= 3) { + (0.. Int { if numbers.count < 3 { return 0 } diff --git a/WeeklyChallenge2022.playground/Pages/Challenge45.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge45.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..f0ec80a --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge45.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,66 @@ +import Foundation + +/* + * Reto #45 + * CONTENEDOR DE AGUA + * Fecha publicación enunciado: 07/10/22 + * Fecha publicación resolución: 14/11/22 + * Dificultad: MEDIA + * + * Enunciado: Dado un array de números enteros positivos, donde cada uno representa unidades + * de bloques apilados, debemos calcular cuantas unidades de agua quedarán atrapadas entre ellos. + * + * - Ejemplo: Dado el array [4, 0, 3, 6, 1, 3]. + * + * ⏹ + * ⏹ + * ⏹💧💧⏹ + * ⏹💧⏹⏹💧⏹ + * ⏹💧⏹⏹💧⏹ + * ⏹💧⏹⏹⏹⏹ + * + * Representando bloque con ⏹︎ y agua con 💧, quedarán atrapadas 7 unidades de agua. + * Suponemos que existe un suelo impermeable en la parte inferior que retiene el agua. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +func getWaterUnits(input: [Int], draw: Bool = true) -> Int { + var result = 0 + let numRows = input.max() ?? 0 + (0.. Direction { + switch(self) { + case .north: + return .west + case .east: + return .north + case .south: + return .east + case .west: + return .south + } + } +} + +private func moveRobot(moves: [Int]) -> (x: Int, y: Int) { + var direction = Direction.north + var x = 0 + var y = 0 + + moves.forEach { move in + switch(direction) { + case .north: + y += move + case .east: + x += move + case .south: + y -= move + case .west: + x -= move + } + direction = direction.turn() + } + return (x, y) +} + +print(moveRobot(moves: [10, 5, -2])) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge47.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge47.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..6172406 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge47.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,35 @@ +import Foundation + +/* + * Reto #47 + * VOCAL MÁS COMÚN + * Fecha publicación enunciado: 21/11/22 + * Fecha publicación resolución: 28/11/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea un función que reciba un texto y retorne la vocal que más veces se repita. + * Si no hay vocales podrá devolver vacío. + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ +func getMostRepeatedVowels(text: String) -> String { + let cleanedText = text.folding(options: .diacriticInsensitive, locale: .current).lowercased() + var vowelOccurrences: [Character : Int] = [:] + cleanedText.forEach { letter in + if("aeiou".contains(letter)) { + vowelOccurrences[letter] = vowelOccurrences[letter] == nil ? 1 : vowelOccurrences[letter]! + 1 + } + } + let maxNumberOfOccurrences = vowelOccurrences.values.max() + return vowelOccurrences.isEmpty ? "" : String(vowelOccurrences.filter{ $0.value == maxNumberOfOccurrences }.keys) +} + +print(getMostRepeatedVowels(text: "¡Pssst!")) +print(getMostRepeatedVowels(text: "¡Hola Brais!")) +print(getMostRepeatedVowels(text: "¡Adiós Brais!")) +print(getMostRepeatedVowels(text: "¡Adiós Martín!")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge48.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge48.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..d2fc27f --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge48.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,109 @@ +import Foundation + +/* + * Reto #48 + * EL CALENDARIO DE ADEVIENTO 2022 + * Fecha publicación enunciado: 28/11/22 + * Fecha publicación resolución: 05/12/22 + * Dificultad: FÁCIL + * + * ¿Conoces el calendario de adviento de la comunidad (https://adviento.dev)? + * 24 días, 24 regalos sorpresa relacionados con desarrollo de software, ciencia y tecnología desde el 1 de diciembre. + * + * Enunciado: Crea una función que reciba un objeto de tipo "Date" y retorne lo siguiente: + * - Si la fecha coincide con el calendario de aDEViento 2022: Retornará el regalo de ese día (a tu elección) y cuánto queda para que finalice el sorteo de ese día. + * - Si la fecha es anterior: Cuánto queda para que comience el calendario. + * - Si la fecha es posterior: Cuánto tiempo ha pasado desde que ha finalizado. + * + * Notas: + * - Tenemos en cuenta que cada día del calendario comienza a medianoche 00:00:00 y finaliza a las 23:59:59. + * - Debemos trabajar con fechas que tengan año, mes, día, horas, minutos y segundos. + * - 🎁 Cada persona que aporte su solución entrará en un nuevo sorteo del calendario de aDEViento hasta el día de su corrección (sorteo exclusivo para quien entregue su solución). + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +import Foundation +import _Concurrency +import PlaygroundSupport + +let dateFormatter = DateFormatter() +dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss" + +func scrapADEVientoPrizeFor(day: Int) async -> String { + let url = URL(string: "https://adviento.dev") + return await withUnsafeContinuation { continuation in + let session = URLSession.shared + let task = session.dataTask(with: url!) { data, response, error in + guard let data = data else { return } + guard let htmlText = String(data: data, encoding: .utf8) else { return } + let days = htmlText.split(separator: ")") + days.indices.forEach { index in + if((index < days.count-1) && days[index].contains("(\(day)/24")) { + var prize = days[index+1].split(separator: "")[0].split(separator: "\">")[1] + if(days[index+1].starts(with: "")[0] + } + continuation.resume(returning: String(prize.replacingOccurrences(of: "", with: "").replacingOccurrences(of: "", with: "").replacingOccurrences(of: """, with: "\""))) + } + } + continuation.resume(returning: "unknown") + } + task.resume() + } +} + +func formatDateFrom(timeInterval: TimeInterval) -> String { + var calendar = Calendar.current + calendar.locale = Locale(identifier: "es") + let formatter = DateComponentsFormatter() + formatter.calendar = calendar + formatter.maximumUnitCount = 1 + formatter.unitsStyle = .full + formatter.zeroFormattingBehavior = .dropAll + formatter.allowedUnits = [.day, .hour, .minute, .second] + return formatter.string(from: timeInterval)! +} + +func showADEVientoInfoFor(date: Date) { + let calendarStartDate = dateFormatter.date(from: "2022/12/01 00:00:00")! + let calendarEndDate = dateFormatter.date(from: "2022/12/24 23:59:59")! + + if(date.timeIntervalSince(calendarStartDate) < 0) { + print("El Calendario de aDEViento 2022 inicia en \(formatDateFrom(timeInterval: abs(date.timeIntervalSince(calendarStartDate))))") + } else if(date.timeIntervalSince(calendarEndDate) > 0) { + print("El Calendario de aDEViento 2022 finalizó hace \(formatDateFrom(timeInterval: date.timeIntervalSince(calendarEndDate)))") + } else { + let dateDay = Calendar.current.dateComponents([.day], from: date) + Task { + let prize = await scrapADEVientoPrizeFor(day: dateDay.day!) + if(prize != "unknown") { + let todayDay = Calendar.current.dateComponents([.day], from: .now) + if(dateDay.day! == todayDay.day!) { + let endDay = dateFormatter.date(from: "2022/12/\(dateDay.day!) 23:59:59")! + print("Quedan \(formatDateFrom(timeInterval: endDay.timeIntervalSince(.now))) para participar en el sorteo de: \(prize)") + } else { + print("El premio fue: \(prize)") + } + } else { + let startDay = dateFormatter.date(from: "2022/12/\(dateDay.day!) 00:00:00")! + print("En \(formatDateFrom(timeInterval: startDay.timeIntervalSince(.now))) se conocerá el premio y comenzará el sorteo.") + } + } + } +} + +showADEVientoInfoFor(date: dateFormatter.date(from: "2022/11/30 23:00:00")!) +showADEVientoInfoFor(date: dateFormatter.date(from: "2022/12/26 01:00:00")!) +//showADEVientoInfoFor(date: dateFormatter.date(from: "2022/12/01 04:00:00")!) +//showADEVientoInfoFor(date: dateFormatter.date(from: "2022/12/02 08:00:00")!) +//showADEVientoInfoFor(date: dateFormatter.date(from: "2022/12/03 12:00:00")!) +//showADEVientoInfoFor(date: dateFormatter.date(from: "2022/12/04 16:00:00")!) +showADEVientoInfoFor(date: .now) +//showADEVientoInfoFor(date: dateFormatter.date(from: "2022/12/07 20:00:00")!) + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge49.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge49.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..030ff47 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge49.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,56 @@ +import Foundation + +/* + * Reto #49 + * EL DETECTOR DE HANDLES + * Fecha publicación enunciado: 05/11/22 + * Fecha publicación resolución: 12/12/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que sea capaz de detectar y retornar todos los handles de un texto usando solamente Expresiones Regulares. + * Debes crear una expresión regular para cada caso: + * - Handle usuario: Los que comienzan por "@" + * - Handle hashtag: Los que comienzan por "#" + * - Handle web: Los que comienzan por "www.", "http://", "https://" y finalizan con un dominio (.com, .es...) + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ + +func detectHandles(from text: String) -> [String] { + let userHandleRegex = try! NSRegularExpression(pattern: "@[a-zA-Z0-9_]+") + let hashtagHandleRegex = try! NSRegularExpression(pattern: "#[a-zA-Z0-9_]+") + let webHandleRegex = try! NSRegularExpression(pattern: "(www\\.[a-zA-Z0-9_]+|https?://[a-zA-Z0-9_]+)(\\.[a-zA-Z]+)+") + + var handles = [String]() + + // Busca handles de usuario + let userHandleMatches = userHandleRegex.matches(in: text, range: NSRange(text.startIndex..., in: text)) + for match in userHandleMatches { + let handle = String(text[Range(match.range, in: text)!]) + handles.append(handle) + } + + // Busca handles de hashtags + let hashtagHandleMatches = hashtagHandleRegex.matches(in: text, range: NSRange(text.startIndex..., in: text)) + for match in hashtagHandleMatches { + let handle = String(text[Range(match.range, in: text)!]) + handles.append(handle) + } + + // Busca handles de web + let webHandleMatches = webHandleRegex.matches(in: text, range: NSRange(text.startIndex..., in: text)) + for match in webHandleMatches { + let handle = String(text[Range(match.range, in: text)!]) + handles.append(handle) + } + + return handles +} + +print(detectHandles(from: "Sorteo #aDEViento2022 - Sábado 10 de diciembre (10/24) - (x2) Libros 'Inteligencia matemática/Apocalipsis matemático' de Eduardo Sáenz de Cabezón - Ganadores/as sorteo: @DanMaG175, @fUIHq39Ym40q4Ul - Más sobre estos libros en https://amzn.to/3F9x16w")) + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge5.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge5.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..7bf8fc2 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge5.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,47 @@ +import Foundation +import ImageIO + +/* + * Reto #5 + * ASPECT RATIO DE UNA IMAGEN + * Fecha publicación enunciado: 01/02/22 + * Fecha publicación resolución: 07/02/22 + * Dificultad: DIFÍCIL + * + * Enunciado: Crea un programa que se encargue de calcular y el aspect ratio de una imagen a partir de una url. + * - Url de ejemplo: https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_github_profile.png + * - Por ratio hacemos referencia por ejemplo a los "16:9" de una imagen de 1920*1080px. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func showAspectRatioOf(imageLink: String) { + let imageURL = URL(string: imageLink)! + let imageName = imageLink.split(separator: "/").last!.split(separator: ".").first! + let source = CGImageSourceCreateWithURL(imageURL as CFURL, nil) + let imageHeader = CGImageSourceCopyPropertiesAtIndex(source!, 0, nil)! as NSDictionary + if let imageWidth = imageHeader["PixelWidth"] as? Int, + let imageHeight = imageHeader["PixelHeight"] as? Int { + var minWidth = imageWidth + var minHeight = imageHeight + (1...min(imageWidth, imageHeight)).forEach { i in + if((imageWidth % i == 0) && (imageHeight % i == 0)) { + minWidth = imageWidth / i + minHeight = imageHeight / i + } + } + print("\(String(describing: imageName)) tiene \(minWidth):\(minHeight) de ratio") + } else { + print("No se ha podido calcular el ratio de \(String(describing: imageName))") + } +} + +showAspectRatioOf(imageLink: "https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_github_profile.png") +showAspectRatioOf(imageLink: "https://upload.wikimedia.org/wikipedia/commons/7/7c/Aspect_ratio_16_9_example.jpg") +showAspectRatioOf(imageLink: "https://upload.wikimedia.org/wikipedia/commons/4/43/Aspect_ratio_4_3_example.jpg") +showAspectRatioOf(imageLink: "https://pbs.twimg.com/profile_images/918389307831934976/22ktBpnu_400x400.jpg") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge5.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge5.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..03fb224 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge5.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,76 @@ +import Foundation +import UIKit + +/* + * Reto #5 + * ASPECT RATIO DE UNA IMAGEN + * Fecha publicación enunciado: 01/02/22 + * Fecha publicación resolución: 07/02/22 + * Dificultad: DIFÍCIL + * + * Enunciado: Crea un programa en Swift que se encargue de calcular el aspect ratio de una imagen a partir de una url. + * - Url de ejemplo: https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_github_profile.png + * - Por ratio hacemos referencia por ejemplo a los "16:9" de una imagen de 1920*1080px. + * + * Resuelto: Sí. + " Iteracciones: 4 + * Explicación: Para calcular el aspect ratio de una imagen en Swift, primero necesitaríamos acceder a la imagen a partir de su URL. Luego, podríamos obtener sus dimensiones (ancho y alto) y calcular el ratio de estos valores. + * Conversación: + * - El aspect ratio se suele mostrar separado por dos puntos (:) + * - Pero, en lugar del ancho y el alto completos, se suelen mostrar los número más pequeños posibles. + * - No reconoce la función gcd() + * Nota: se inventa que gcd es una función de la librería de Swift + */ + +// Define una función gcd que recibe dos enteros y devuelve su máximo común divisor +func gcd(_ a: Int, _ b: Int) -> Int { + // Si uno de los números es cero, devuelve el otro número + if a == 0 { + return b + } else if b == 0 { + return a + } + + // Si ambos números son iguales, devuelve uno de ellos + if a == b { + return a + } + + // Si el primer número es mayor que el segundo, intercambia ambos valores + if a > b { + return gcd(a - b, b) + } else { + return gcd(a, b - a) + } +} + +// URL de ejemplo +// let url = URL(string: "https://raw.githubusercontent.com/mouredev/mouredev/master/mouredev_github_profile.png")! +// let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/7/7c/Aspect_ratio_16_9_example.jpg")! +let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/4/43/Aspect_ratio_4_3_example.jpg")! +// let url = URL(string: "https://pbs.twimg.com/profile_images/918389307831934976/22ktBpnu_400x400.jpg")! + +// Luego, cargamos la imagen en una variable de tipo UIImage +let image = UIImage(data: try! Data(contentsOf: url))! + +// A continuación, podemos obtener las dimensiones de la imagen +let width = image.size.width +let height = image.size.height + +// Calculamos el máximo común divisor (MCD) de los valores del ancho y del alto +let mcd = gcd(Int(width), Int(height)) + +// Dividimos los valores del ancho y del alto por el MCD para obtener +// los números más pequeños posibles +let aspectRatio = (Int(width) / mcd, Int(height) / mcd) + +// Usamos la función String(format:) para formatear el resultado +// como "ancho:alto" +let aspectRatioString = String(format: "%d:%d", aspectRatio.0, aspectRatio.1) + +// Imprimimos el resultado en consola +print(aspectRatioString) + + + + diff --git a/WeeklyChallenge2022.playground/Pages/Challenge50.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge50.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..380aa6c --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge50.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,47 @@ +import Foundation + +/* + * Reto #50 + * LA ENCRIPTACIÓN DE KARACA + * Fecha publicación enunciado: 12/11/22 + * Fecha publicación resolución: 19/12/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea una función que sea capaz de encriptar y desencriptar texto utilizando el + * algoritmo de encriptación de Karaca (debes buscar información sobre él). + * + * Información adicional: + * - Usa el canal de nuestro Discord (https://mouredev.com/discord) "🔁reto-semanal" + * para preguntas, dudas o prestar ayuda a la comunidad. + * - Tienes toda la información sobre los retos semanales en + * https://retosdeprogramacion.com/semanales2022. + * + */ +let vowels = "aeiou" + +func karacaEncrypt(_ text: String) -> String { + var result = "" + text.reversed().forEach { letter in + result = "\(result)\(vowels.contains(letter) ? String(vowels.firstIndex(of: letter)!.utf16Offset(in: vowels)) : String(letter))" + } + return "\(result)aca" +} + +func karacaDecrypt(_ text: String) -> String { + var result = "" + text[.. String { + var result = "" + for char in self { + result = "\(char)\(result)" + } + return result + } +} + +print("Hola mundo".reverse()) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge6.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge6.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..36af307 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge6.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,68 @@ +import Foundation + +/* + * Reto #6 + * INVIRTIENDO CADENAS + * Fecha publicación enunciado: 07/02/22 + * Fecha publicación resolución: 14/02/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea un programa que invierta el orden de una cadena de texto sin usar funciones propias del lenguaje que lo hagan de forma automática. + * - Si le pasamos "Hola mundo" nos retornaría "odnum aloH" + * + * Resuelto: Sí. Pero hay que aclararle que no utilice funciones del sistema. + " Iteracciones: 3 + * Explicación: Para crear un programa en Swift que invierta el orden de una cadena de texto sin usar funciones propias del lenguaje que lo hagan de forma automática, podemos utilizar un ciclo for y la propiedad .reversed() de las secuencias de caracteres de Swift. + * Conversación: + * - Pero al utilizar la función reversed() no cumplimos con el enunciado. + * - ¿Y cómo sería la implementación de la función invertirCadena de forma recursiva? + * + */ + +// Creamos una función que toma como parámetro una cadena de texto y la retorna invertida +func invertirCadena(cadena: String) -> String { + // Creamos una variable que almacenará la cadena invertida + var cadenaInvertida = "" + + // Recorremos la cadena original desde el último caracter hasta el primero + for i in stride(from: cadena.count - 1, through: 0, by: -1) { + // Agregamos cada caracter a la cadena invertida + cadenaInvertida.append(cadena[cadena.index(cadena.startIndex, offsetBy: i)]) + } + + // Retornamos la cadena invertida + return cadenaInvertida +} + +// Creamos una variable que contiene la cadena que queremos invertir +let cadenaOriginal = "Hola mundo" + +// Invertimos la cadena y almacenamos el resultado en otra variable +var cadenaInvertida = invertirCadena(cadena: cadenaOriginal) + +// Imprimimos la cadena invertida en la consola +print(cadenaInvertida) // debería imprimir "odnum aloH" + +// Creamos una función que toma como parámetro una cadena de texto y la retorna invertida +func invertirCadenaRecurvisamente(cadena: String) -> String { + // Si la cadena tiene 0 o 1 caracter, retornamos la cadena tal cual + if cadena.count <= 1 { + return cadena + } + + // Extraemos el último caracter de la cadena + let ultimoCaracter = cadena[cadena.index(before: cadena.endIndex)] + + // Invocamos la función recursivamente, pero quitando el último caracter de la cadena + let cadenaSinUltimoCaracter = cadena[cadena.startIndex.. String { + var result = "" + for char in self { + result = "\(char)\(result)" + } + return result print(reverse(text: "Hola mundo")) print(recursiveReverse(text: "Hola mundo")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge7.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge7.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..55c87ff --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge7.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,31 @@ +import Foundation + +/* + * Reto #7 + * CONTANDO PALABRAS + * Fecha publicación enunciado: 14/02/22 + * Fecha publicación resolución: 21/02/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa que cuente cuantas veces se repite cada palabra y que muestre el recuento final de todas ellas. + * - Los signos de puntuación no forman parte de la palabra. + * - Una palabra es la misma aunque aparezca en mayúsculas y minúsculas. + * - No se pueden utilizar funciones propias del lenguaje que lo resuelvan automáticamente. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func countWords(phrase: String) { + let text = phrase.lowercased().components(separatedBy: CharacterSet.punctuationCharacters).joined(separator: "") + Set(text.split(separator: " ")).forEach { word in + let wordOccurrences = text.components(separatedBy: word).count - 1 + print("\(word.uppercased()) aparece \(wordOccurrences) \(wordOccurrences > 1 ? "veces" : "vez") en la frase") + } +} + +countWords(phrase: "Hola Brais, yo no me llamo brais.") diff --git a/WeeklyChallenge2022.playground/Pages/Challenge7.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge7.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..a10ef23 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge7.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,53 @@ +import Foundation + +/* + * Reto #7 + * CONTANDO PALABRAS + * Fecha publicación enunciado: 14/02/22 + * Fecha publicación resolución: 21/02/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa en Swift que cuente cuantas veces se repite cada palabra y que muestre el recuento final de todas ellas. + * - Los signos de puntuación no forman parte de la palabra. + * - Una palabra es la misma aunque aparezca en mayúsculas y minúsculas. + * - No se pueden utilizar funciones propias del lenguaje que lo resuelvan automáticamente. + * + * Resuelto: Sí + " Iteracciones: º + * Explicación: Este programa toma una cadena de texto ingresada por el usuario, divide la cadena en un array de palabras, luego recorre el array y cuenta cuántas veces aparece cada palabra en el texto. Finalmente, muestra el recuento de cada palabra. + * + */ + +let texto = "Hola, mi nombre es brais. Mi nombre completo es Brais Moure (MoureDev)." +//let texto = "Hola Brais, yo no me llamo brais." + +// Creamos un diccionario vacío para almacenar las palabras y sus contadores +var contadores = [String: Int]() + +// Dividimos la cadena de texto en un array de palabras +let palabras = texto.components(separatedBy: .whitespacesAndNewlines) + +// Recorremos el array de palabras y actualizamos el contador en el diccionario +// para cada palabra +for palabra in palabras { + // Quitamos los signos de puntuación de la palabra + let sinPuntuacion = palabra.trimmingCharacters(in: .punctuationCharacters) + + // Convertimos la palabra a minúsculas para que no se distingan mayúsculas + // y minúsculas + let palabraLimpia = sinPuntuacion.lowercased() + + // Verificamos si la palabra ya está en el diccionario + if let contador = contadores[palabraLimpia] { + // Si ya existe, incrementamos su contador + contadores[palabraLimpia] = contador + 1 + } else { + // Si no existe, la agregamos al diccionario con contador 1 + contadores[palabraLimpia] = 1 + } +} + +// Recorremos el diccionario y mostramos el recuento de cada palabra +for (palabra, contador) in contadores { + print("La palabra '\(palabra)' se repite \(contador) veces") +} diff --git a/WeeklyChallenge2022.playground/Pages/Challenge8.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge8.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..1a423eb --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge8.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,30 @@ +import Foundation + +/* + * Reto #8 + * DECIMAL A BINARIO + * Fecha publicación enunciado: 18/02/22 + * Fecha publicación resolución: 02/03/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea un programa se encargue de transformar un número decimal a binario sin utilizar funciones propias del lenguaje que lo hagan directamente. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda la acomunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func getBinary(decimal: Int) -> String { + if(decimal < 2) { + return "\(decimal % 2)" + } else { + return "\(getBinary(decimal: decimal / 2))\(decimal % 2)" + } +} + +[1024, 432, 79, 25, 1, 0].forEach { num in + print("Binario de \(num) es \(getBinary(decimal: num))") +} diff --git a/WeeklyChallenge2022.playground/Pages/Challenge8.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge8.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..411f102 --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge8.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,63 @@ +import Foundation + +/* + * Reto #8 + * DECIMAL A BINARIO + * Fecha publicación enunciado: 18/02/22 + * Fecha publicación resolución: 02/03/22 + * Dificultad: FÁCIL + * + * Enunciado: Crea un programa en Swift que se encargue de transformar un número decimal a binario sin utilizar funciones propias del lenguaje que lo hagan directamente. + * + * Resuelto: Sí + " Iteracciones: 3 + * Explicación: Para transformar un número decimal a binario en Swift, puedes utilizar un algoritmo de división sucesiva. + En este ejemplo, la función decimalToBinary toma un número entero y lo divide repetidamente entre 2, agregando el residuo de cada división al resultado. Una vez que el número se ha dividido hasta llegar a 0, se devuelve el resultado como una cadena de caracteres. + * Conversación: + * - El código intenta cambiar el valor del parámetro number que es inmutable + * - Para el caso del número 0 devuelve un resultado vacío, en lugar de 0 + * + */ + +// Declara una función que recibe un número entero y lo convierte a binario +func decimalToBinary(_ number: Int) -> String { + // Crea una variable local para almacenar el número + var localNumber = number + + // Crea una variable para almacenar el resultado + var binary = "" + + // Si el número es 0, devuelve 0 + if number == 0 { + return "0" + } + + // Repite hasta que el número sea 0 + while localNumber != 0 { + // Agrega el residuo de la división del número entre 2 al resultado + binary = String(localNumber % 2) + binary + + // Divide el número entre 2 + localNumber /= 2 + } + + // Devuelve el resultado + return binary +} + +// Prueba la función convirtiendo algunos números decimales a binarios +print(decimalToBinary(0)) // 0 +print(decimalToBinary(1)) // 1 +print(decimalToBinary(2)) // 10 +print(decimalToBinary(3)) // 11 +print(decimalToBinary(4)) // 100 +print(decimalToBinary(5)) // 101 + +// Brais cases +print(decimalToBinary(387)) //110000011 + +// Jaime cases +print(decimalToBinary(1024))//10000000000 +print(decimalToBinary(432)) //110110000 +print(decimalToBinary(79)) //1001111 +print(decimalToBinary(25)) //11001 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge8.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge8.xcplaygroundpage/Contents.swift index 389cf09..2292955 100644 --- a/WeeklyChallenge2022.playground/Pages/Challenge8.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Challenge8.xcplaygroundpage/Contents.swift @@ -33,5 +33,5 @@ func decimalToBinary(_ decimal: Int) -> String { return binary.isEmpty ? "0" : binary } -print(decimalToBinary(387)) -print(decimalToBinary(0)) +print(decimalToBinary(387)) //110000011 +print(decimalToBinary(0)) //0 diff --git a/WeeklyChallenge2022.playground/Pages/Challenge9.jaimefere.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge9.jaimefere.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..e80188b --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge9.jaimefere.xcplaygroundpage/Contents.swift @@ -0,0 +1,97 @@ +import Foundation + +/* + * Reto #9 + * CÓDIGO MORSE + * Fecha publicación enunciado: 02/03/22 + * Fecha publicación resolución: 07/03/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa que sea capaz de transformar texto natural a código morse y viceversa. + * - Debe detectar automáticamente de qué tipo se trata y realizar la conversión. + * - En morse se soporta raya "—", punto ".", un espacio " " entre letras o símbolos y dos espacios entre palabras " ". + * - El alfabeto morse soportado será el mostrado en https://es.wikipedia.org/wiki/Código_morse. + * + * Información adicional: + * - Usa el canal de nuestro discord (https://mouredev.com/discord) "🔁reto-semanal" para preguntas, dudas o prestar ayuda a la comunidad. + * - Puedes hacer un Fork del repo y una Pull Request al repo original para que veamos tu solución aportada. + * - Revisaré el ejercicio en directo desde Twitch el lunes siguiente al de su publicación. + * - Subiré una posible solución al ejercicio el lunes siguiente al de su publicación. + * + */ + +func toMorse(alphabet: [String: String], input: String) -> String { + var output = input + alphabet.keys.forEach { + output = output.replacingOccurrences(of: $0, with: alphabet[$0]! + " ") + } + return output +} + +func toStandard(alphabet: [String: String], input: String) -> String { + var output = "" + input.components(separatedBy: " ").forEach { word in + word.split(separator: " ").forEach { morseSecuence in + output += alphabet.first{ $1 == morseSecuence }!.key + } + output += " " + } + return output +} + +func translate(text: String) -> String { + var alphabet = [String: String]() + alphabet[" "] = "" + alphabet["CH"] = "————" + alphabet["A"] = "·—" + alphabet["B"] = "—···" + alphabet["C"] = "—·—·" + alphabet["D"] = "—··" + alphabet["E"] = "·" + alphabet["F"] = "··—·" + alphabet["G"] = "——·" + alphabet["H"] = "····" + alphabet["I"] = "··" + alphabet["J"] = "·———" + alphabet["K"] = "—·—" + alphabet["L"] = "·—··" + alphabet["M"] = "——" + alphabet["N"] = "—·" + alphabet["Ñ"] = "——·——" + alphabet["O"] = "———" + alphabet["P"] = "·——·" + alphabet["Q"] = "——·—" + alphabet["R"] = "·—·" + alphabet["S"] = "···" + alphabet["T"] = "—" + alphabet["U"] = "··—" + alphabet["V"] = "···—" + alphabet["W"] = "·——" + alphabet["X"] = "—··—" + alphabet["Y"] = "—·——" + alphabet["Z"] = "——··" + alphabet["0"] = "—————" + alphabet["1"] = "·————" + alphabet["2"] = "··———" + alphabet["3"] = "···——" + alphabet["4"] = "····—" + alphabet["5"] = "·····" + alphabet["6"] = "—····" + alphabet["7"] = "——···" + alphabet["8"] = "———··" + alphabet["9"] = "————·" + alphabet["."] = "·—·—·—" + alphabet[","] = "——··——" + alphabet["?"] = "··——··" + alphabet["\""] = "·—··—·" + alphabet["/"] = "—··—·" + + if(alphabet.keys.filter{ $0 != " " && text.contains($0) }.count > 0) { + return toMorse(alphabet: alphabet, input: text.uppercased()) + } else { + return toStandard(alphabet: alphabet, input: text.uppercased()) + } +} + +print(translate(text: "De texto a Morse")) +print(translate(text: "—·· · —— ——— ·—· ··· · ·— — · —··— — ——— ")) diff --git a/WeeklyChallenge2022.playground/Pages/Challenge9.openai.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Challenge9.openai.xcplaygroundpage/Contents.swift new file mode 100644 index 0000000..e636d7a --- /dev/null +++ b/WeeklyChallenge2022.playground/Pages/Challenge9.openai.xcplaygroundpage/Contents.swift @@ -0,0 +1,148 @@ +import Foundation + +/* + * Reto #9 + * CÓDIGO MORSE + * Fecha publicación enunciado: 02/03/22 + * Fecha publicación resolución: 07/03/22 + * Dificultad: MEDIA + * + * Enunciado: Crea un programa en Swift que sea capaz de transformar texto natural a código morse y viceversa. + * — Debe detectar automáticamente de qué tipo se trata y realizar la conversión. + * — En morse se soporta raya "—", punto ".", un espacio " " entre letras o símbolos y dos espacios entre palabras " ". + * — El alfabeto morse soportado será el mostrado en https://es.wikipedia.org/wiki/Código_morse. + * + * Resuelto: Sí + " Iteracciones: 2 + * Explicación: Para crear este programa en Swift, podemos utilizar el diccionario de código morse para convertir un texto a morse y viceversa. Primero, definimos el diccionario como una estructura de datos de tipo [String: String] + Luego, podemos crear una función que tome una cadena de texto como entrada y devuelva la cadena convertida a morse o a texto según sea necesario. + Para convertir de morse a texto, podemos usar una función similar, pero en lugar de iterar sobre los caracteres de la cadena de texto, iteramos sobre las palabras en la cadena de morse. + Para detectar automáticamente si la cadena de entrada es texto o morse, podemos utilizar una expresión regular para verificar si la cadena contiene sólo puntos y rayas. Si la cadena contiene sólo puntos y rayas, entonces es morse, de lo contrario es texto. + * Conversación: + * — En el alfabeto faltan equivalencias para la letra CH, para paréntesis, para símbolos de puntuación, de exclamación y de interrogación. Complétalo añadiendo todos los símbolos que se te ocurran + * + */ + +// Creamos un diccionario que contenga las letras del alfabeto y los símbolos que mencionas, junto con su equivalente en código morse +let morseAlphabet: [String: String] = [ + "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": "—————", + "CH": "————", + "(": "—·——·", + ")": "—·——·—", + ":": "———···", + ",": "——··——", + "=": "—···—", + "?": "··——··", + "'": "·————·", + "/": "—··—·", + "!": "—·—·——", + ".": "·—·—·—", + "—": "—····—", + "+": "·—·—·", + "@": "·——·—·" +] + +func convertToMorse(text: String) -> String { + var morse = "" + // Iteramos sobre cada caracter de la cadena de texto + for char in text { + // Convertimos el caracter a mayúsculas para que la búsqueda en el diccionario funcione correctamente + let upperChar = String(char).uppercased() + // Si el caracter está en el diccionario, lo agregamos a la cadena de morse + if let code = morseAlphabet[upperChar] { + morse += code + " " + } + } + // Devolvemos la cadena de morse sin el último espacio + return String(morse.dropLast()) +} + +func convertToText(morse: String) -> String { + var text = "" + // Separamos la cadena de morse en palabras utilizando el espacio como separador + let words = morse.components(separatedBy: " ") + // Iteramos sobre cada palabra + for word in words { + // Separamos la palabra en caracteres utilizando el espacio como separador + let chars = word.components(separatedBy: " ") + // Iteramos sobre cada caracter + for char in chars { + // Buscamos el código morse en el diccionario + if let letter = morseAlphabet.first(where: { $0.value == char })?.key { + // Si lo encontramos, lo agregamos a la cadena de texto + text += letter + } + } + // Agregamos un espacio después de cada palabra + text += " " + } + // Devolvemos la cadena de texto sin el último espacio + return String(text.dropLast()) +} + +func convert(input: String) -> String { + // Verificamos si la cadena contiene sólo puntos y rayas + let morseRegex = try! NSRegularExpression(pattern: "^[\\·\\—\\s]+$") + let isMorse = morseRegex.firstMatch(in: input, range: NSRange(input.startIndex..., in: input)) != nil + + if isMorse { + // Si es morse, convertimos a texto + return convertToText(morse: input) + } else { + // Si es texto, convertimos a morse + return convertToMorse(text: input) + } +} + +print(convert(input: "SOS")) // => "... --- ..." +print(convert(input: "··· ——— ···")) // => "SOS" + +//Brais cases +print(convert(input: "Chocapic. Es una marca de cereales?")) // => "———— ——— —·—· ·— ·——· ·· —·—· ·—·—·— · ··· ··— —· ·— —— ·— ·—· —·—· ·— —·· · —·—· · ·—· · ·— ·—·· · ··· ··——··" +print(convert(input: "———— ——— —·—· ·— ·——· ·· —·—· ·—·—·— · ··· ··— —· ·— —— ·— ·—· —·—· ·— —·· · —·—· · ·—· · ·— ·—·· · ··· ··——··")) // => "Chocapic. Es una marca de cereales?" + + +//Jaime cases +print(convert(input: "De texto a Morse")) // => "—·· · — · —··— — ——— ·— —— ——— ·—· ··· ·" +print(convert(input: "—·· · —— ——— ·—· ··· · ·— — · —··— — ———")) // => "DE MORSE A TEXTO" + + + + + + diff --git a/WeeklyChallenge2022.playground/Pages/Readme.xcplaygroundpage/Contents.swift b/WeeklyChallenge2022.playground/Pages/Readme.xcplaygroundpage/Contents.swift index 4429305..21ad073 100644 --- a/WeeklyChallenge2022.playground/Pages/Readme.xcplaygroundpage/Contents.swift +++ b/WeeklyChallenge2022.playground/Pages/Readme.xcplaygroundpage/Contents.swift @@ -7,3 +7,4 @@ * Recuerda que puedes ejecutar código Swift de una forma muy simple * pulsando el botón de "play ►" en el lateral. */ + diff --git a/WeeklyChallenge2022.playground/contents.xcplayground b/WeeklyChallenge2022.playground/contents.xcplayground index 0cda066..3eb58d0 100644 --- a/WeeklyChallenge2022.playground/contents.xcplayground +++ b/WeeklyChallenge2022.playground/contents.xcplayground @@ -3,55 +3,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - \ No newline at end of file +