Skip to content

Instantly share code, notes, and snippets.

@fedescarpa
Last active May 20, 2020 15:42
Show Gist options
  • Save fedescarpa/947e5a1ffa3fcf4ea6e72b745ceb7128 to your computer and use it in GitHub Desktop.
Save fedescarpa/947e5a1ffa3fcf4ea6e72b745ceb7128 to your computer and use it in GitHub Desktop.
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