Last active
May 20, 2020 15:42
-
-
Save fedescarpa/947e5a1ffa3fcf4ea6e72b745ceb7128 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module TierraDeBarbaros where | |
{- | |
Tierra de Bárbaros | |
Rechapos! - En la tierra de Udrogoth los reyes bárbaros formaron un imperio de guerreros, dragones y magia. | |
Ahora marcharon a la guerra contra el mal y dejaron a sus herederos a cargo.... y bueno, hay que conformarse. | |
Sin embargo, nos encargaron confeccionar un programa en Haskell para manejar los asuntos del reino, y evitar | |
así el tener que gobernar. | |
Consideraciones: | |
Escribir el tipo de todas las funciones principales | |
Emplear sinónimos de tipo cuando sea posible. | |
No se permite usar recursividad salvo que se indique lo contrario | |
Definir las funciones en estilo point-free cuando sea posible | |
Punto 1 | |
Se sabe que los bárbaros tienen nombre, fuerza, habilidades y objetos, | |
que los ayudarán más adelante en su lucha contra el mal. Por ejemplo: | |
-} | |
import Text.Show.Functions | |
import Data.Char | |
data Barbaro = Barbaro { | |
nombre :: String, | |
fuerza :: Int, | |
habilidades :: [Habilidad], | |
objetos :: [Objeto] | |
} deriving (Show) | |
mapNombre :: (String -> String) -> Barbaro -> Barbaro | |
mapNombre funcion barbaro = barbaro { nombre = funcion (nombre barbaro) } | |
mapFuerza :: (Int -> Int) -> Barbaro -> Barbaro | |
mapFuerza funcion barbaro = barbaro { fuerza = funcion (fuerza barbaro) } | |
mapHabilidades :: ([Habilidad] -> [Habilidad]) -> Barbaro -> Barbaro | |
mapHabilidades funcion barbaro = barbaro { habilidades = funcion (habilidades barbaro) } | |
mapObjetos :: ([Objeto] -> [Objeto]) -> Barbaro -> Barbaro | |
mapObjetos funcion barbaro = barbaro { objetos = funcion (objetos barbaro) } | |
type Objeto = Barbaro -> Barbaro | |
type Habilidad = String | |
dave = Barbaro "Dave" 100 ["tejer", "escribirPoesia"] [ardilla, amuletosMisticos "Tejer", espada 5] | |
{- | |
Se pide definir los siguientes objetos y definir algunos bárbaros de ejemplo | |
* Las espadas aumentan la fuerza de los bárbaros en 2 unidades por cada kilogramo de peso. | |
* Los amuletosMisticos otorgan una habilidad dada a un bárbaro. | |
* Las varitasDefectuosas, añaden la habilidad de hacer magia, pero desaparecen todos los demás objetos del bárbaro. | |
* Una ardilla, que no hace nada. | |
* Una cuerda, que combina dos objetos distintos,obteniendo uno que realiza las transformaciones de los otros dos. | |
-} | |
espada :: Int -> Objeto | |
espada peso = mapFuerza (+ (peso * 2)) | |
amuletosMisticos :: Habilidad -> Objeto | |
amuletosMisticos habilidad = agregarHabilidad habilidad | |
varitasDefectuosas :: Objeto | |
varitasDefectuosas = mapObjetos (const []) . agregarHabilidad "hacerMagia" | |
ardilla :: Objeto | |
ardilla barbaro = barbaro | |
cuerda :: Objeto -> Objeto -> Objeto | |
cuerda objeto1 objeto2 = objeto2 . objeto1 | |
agregarHabilidad :: Habilidad -> Barbaro -> Barbaro | |
agregarHabilidad habilidad barbaro = mapHabilidades (habilidad :) barbaro | |
{- | |
Punto 2 | |
El megafono es un objeto que potencia al bárbaro, concatenando sus habilidades y poniéndolas en mayúsculas. | |
*Main> megafono dave | |
Barbaro "Dave" 100 ["TEJERESCRIBIRPOESIA"] [<function>,<function>] | |
Sabiendo esto, definir al megafono, y al objeto megafonoBarbarico, que está formado por una cuerda, una ardilla y un megáfono. | |
-} | |
megafono :: Objeto | |
megafono barbaro = mapHabilidades (\habilidades -> [map toUpper (concat habilidades)]) barbaro | |
megafonoBarbarico :: Objeto | |
megafonoBarbarico = cuerda ardilla megafono | |
{- | |
Punto 3 - Aventuras | |
Los bárbaros suelen ir de aventuras por el reino luchando contra las fuerzas del mal, | |
pero ahora que tienen nuestra ayuda, quieren que se les diga si un grupo de bárbaros puede | |
sobrevivir a cierta aventura. Una aventura se compone de uno o más eventos, por ejemplo: | |
* invasionDeSuciosDuendes: Un bárbaro sobrevive si sabe “Escribir Poesía Atroz” | |
* cremalleraDelTiempo: Un bárbaro sobrevive si no tiene pulgares. Los bárbaros llamados Faffy y Astro no tienen pulgares, | |
los demás sí. | |
* ritualDeFechorias: Un bárbaro puede sobrevivir si pasa una o más pruebas como las siguientes: | |
* saqueo: El bárbaro debe tener la habilidad de robar y tener más de 80 de fuerza. | |
* gritoDeGuerra: El bárbaro debe tener un poder de grito de guerra igual a la cantidad de letras de sus habilidades. | |
El poder necesario para aprobar es 4 veces la cantidad de objetos del bárbaro. | |
* caligrafia: El bárbaro tiene caligrafía perfecta (para el estándar barbárico de la época) si sus | |
habilidades contienen más de 3 vocales y comienzan con mayúscula. | |
Sabiendo esto, se pide: | |
Definir los eventos, modelar las aventuras y dar un ejemplo. | |
-} | |
type Aventura = [Evento] | |
type Evento = Barbaro -> Bool | |
type Prueba = Evento | |
invasionDeSuciosDuendes :: Evento | |
invasionDeSuciosDuendes barbaro = sabe "Escribir Poesía Atroz" barbaro | |
cremalleraDelTiempo :: Evento | |
cremalleraDelTiempo barbaro = (not . tienePulgares . nombre) barbaro | |
ritualDeFechorias :: [Prueba] -> Evento | |
ritualDeFechorias pruebas barbaro = any ($ barbaro) pruebas | |
saqueo :: Prueba | |
saqueo barbaro = sabe "Robar" barbaro && fuerza barbaro > 80 | |
gritoDeGuerra :: Prueba | |
gritoDeGuerra barbaro = (length . concat . habilidades) barbaro == ((4*) . length . objetos) barbaro | |
caligrafia :: Prueba | |
caligrafia barbaro = all esCaligrafiaPerfecta (habilidades barbaro) | |
esCaligrafiaPerfecta :: Habilidad -> Bool | |
esCaligrafiaPerfecta habilidad = cantidadVocales habilidad > 3 && comienzaConMayuscula habilidad | |
cantidadVocales :: Habilidad -> Int | |
cantidadVocales habilidad = length (filter esVocal habilidad) | |
esVocal :: Char -> Bool | |
esVocal letra = elem letra "aeiou" | |
comienzaConMayuscula :: Habilidad -> Bool | |
comienzaConMayuscula habilidad = isUpper (head habilidad) | |
tienePulgares :: String -> Bool | |
tienePulgares "Astro" = False | |
tienePulgares "Faffy" = False | |
tienePulgares _ = True | |
sabe :: Habilidad -> Barbaro -> Bool | |
sabe habilidad barbaro = elem habilidad (habilidades barbaro) | |
{- | |
Definir la función sobrevivientes que tome una lista de bárbaros y una aventura, | |
y diga cuáles bárbaros la sobreviven (es decir, pasan todas las pruebas) | |
-} | |
sobrevivientes :: [Barbaro] -> Aventura -> [Barbaro] | |
sobrevivientes unosBarbaros unaAventura = filter (sobrevive unaAventura) unosBarbaros | |
sobrevive :: Aventura -> Barbaro -> Bool | |
sobrevive unaAventura unBarbaro = all ($ unBarbaro) unaAventura | |
{- | |
Punto 4 - Dinastía | |
A - Los bárbaros se marean cuando tienen varias habilidades iguales. | |
Por todo esto, nos piden desarrollar una función que elimine los elementos repetidos de una lista | |
(sin utilizar nub ni nubBy) | |
> sinRepetidos [1,2,3,4,4,5,5,6,7] | |
[1,2,3,4,5,6,7] | |
Nota: Puede usarse recursividad para este punto. | |
-} | |
sinRepetidos [] = [] | |
sinRepetidos (x:xs) = x : sinRepetidos (filter (/= x) xs) | |
{- | |
B - Los bárbaros son una raza muy orgullosa, tanto que quieren saber cómo van a ser sus descendientes y | |
asegurarse de que los mismos reciban su legado. | |
El descendiente de un bárbaro comparte su nombre, y un asterisco por cada generación. | |
Por ejemplo "Dave*", "Dave**" , "Dave***" , etc. | |
Además, tienen en principio su mismo poder, habilidades sin repetidos, y los objetos de su padre, | |
pero antes de pasar a la siguiente generación, utilizan (aplican sobre sí mismos) los objetos. | |
Por ejemplo, el hijo de Dave será equivalente a: | |
(ardilla.varitasDefectuosas) (Barbaro "Dave*" 100 ["tejer","escribirPoesia"] [ardilla, varitasDefectuosas]) | |
Definir la función descendientes, que dado un bárbaro nos de sus infinitos descendientes. | |
-} | |
descendientes :: Barbaro -> [Barbaro] | |
descendientes barbaro = iterate descendiente barbaro | |
descendiente :: Barbaro -> Barbaro | |
descendiente barbaro = (mapHabilidades sinRepetidos . mapNombre (++ "*") . aplicarObjetos) barbaro | |
aplicarObjetos :: Barbaro -> Barbaro | |
aplicarObjetos barbaro = foldl (.) id (objetos barbaro) barbaro | |
aplicarObjetos2 :: Barbaro -> Barbaro | |
aplicarObjetos2 barbaro = foldr ($) barbaro (objetos barbaro) | |
{- | |
C. Pregunta: ¿Se podría aplicar sinRepetidos sobre la lista de objetos? ¿Y sobre el nombre de un bárbaro? ¿Por qué? | |
* No porque los objetos son funciones y estas no pueden ser comparadas con (==) ni con (/=). No son Eq. | |
* Sí, porque el nombre es una lista de caracteres y los caracteres pueden ser comparados por (==). Son Eq | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment