Skip to content

Instantly share code, notes, and snippets.

@guille-acosta
Last active August 11, 2021 01:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guille-acosta/5a97b7c0da406d449d857f912dbbae60 to your computer and use it in GitHub Desktop.
Save guille-acosta/5a97b7c0da406d449d857f912dbbae60 to your computer and use it in GitHub Desktop.
Recuperatorio PdeP Funcional 2021 Scarcella
{----------------------------------- PdeP: Puños de Furia --------------------------------------------
Queremos desarrollar un programa que analice y calcule el resultado de los enfrentamientos entre
peleadores de artes marciales, utilizando el paradigma funcional.
1) Necesitamos armar nuestro modelo base.
a. Modelar a los peleadores, de los cuales se conocen sus puntos de vida, su resistencia y el
conjunto de los ataques que conoce.
b. Implementar las siguientes operaciones sobre peleadores, basándonos en el modelo anterior:
-----------------------------------------------------------------------------------------------------}
type Vida = Int
type Resistencia = Int
type Ataque = Peleador -> Peleador
data Peleador = Peleador {
vida :: Vida,
resistencia :: Resistencia,
ataques :: [Ataque]
}
------------------------------------------------------------------------------------------------------
-- i. estaMuerto: Un peleador está muerto si su vida es menor a 1.
------------------------------------------------------------------------------------------------------
estaMuerto :: Peleador -> Bool
estaMuerto = ( 1 > ) . vida
------------------------------------------------------------------------------------------------------
-- ii. esHabil: Un peleador es hábil cuando conoce más de 10 ataques.
------------------------------------------------------------------------------------------------------
esHabil :: Peleador -> Bool
esHabil = ( 10 < ) . length . ataques
{-----------------------------------------------------------------------------------------------------
c. Modelar los ataques, e implementar los siguientes de forma tal que puedan ser incluidos
en el conjunto conocido por un peleador:
-----------------------------------------------------------------------------------------------------}
-- Funcion auxiliar para las funciones 'Ataque'
cambiarPuntosDeVida :: (Peleador -> Vida) -> Peleador -> Peleador
cambiarPuntosDeVida delta peleador = peleador{ vida = delta peleador }
{----------------------------------------------------------------------------------------------------
i. golpe: Reduce la vida del peleador oponente en una cantidad igual a la intensidad del
golpe dividido la resistencia del oponente. (Por ejemplo, un golpe de intensidad 25 haría
perder 3 puntos de vida a un oponente con resistencia 7: 25 `div` 7 == 3).
-----------------------------------------------------------------------------------------------------}
type Intensidad = Int
golpe :: Intensidad -> Ataque
golpe intensidad =
cambiarPuntosDeVida (\oponente -> vida oponente - intensidad `div` resistencia oponente)
------------------------------------------------------------------------------------------------------
--ii . toque de la muerte: El toque d la muerte hace que el oponente pierda toda su vida.
------------------------------------------------------------------------------------------------------
toqueDeLaMuerte :: Ataque
toqueDeLaMuerte = cambiarPuntosDeVida ( ( 0 * ) . vida )
{-----------------------------------------------------------------------------------------------------
iii. patada: Las patadas causan distintos efectos dependiendo en qué parte del cuerpo el oponente
las reciba:
- Una patada en el pecho hace que un oponente vivo pierda 10 puntos de vida, pero reanima el
corazón de un oponente muerto, haciéndole ganar 1 punto de vida.
- Una patada en la carita hace que cualquier oponente pierda la mitad de la vida que le queda.
- Una patada en la nuca no causa ningún daño, pero hace que el oponente olvide su primer ataque,
si es que conoce alguno.
- Una patada en cualquier otra parte del cuerpo no hace nada. Es necesario poder representar los
otros lugares aunque no causen ningún efecto. (Por ejemplo, una patada en la nuca haría que un
oponente que sólo sabe hacer el toque de la muerte se quede sin ataques, mientras que una patada
a, digamos, la pantorrilla o la axila, no le haría nada).
-----------------------------------------------------------------------------------------------------}
patada :: String -> Ataque
patada parteDelCuerpo peleador
| parteDelCuerpo == "pecho" && (not . estaMuerto $peleador) =
cambiarPuntosDeVida ( ( (-10) + ) . vida ) peleador
| parteDelCuerpo == "pecho" && estaMuerto peleador =
cambiarPuntosDeVida ( ( 1 + ) . vida ) peleador
| parteDelCuerpo == "carita" = cambiarPuntosDeVida ( ( `div` 2) . vida ) peleador
| parteDelCuerpo == "nuca" = peleador{ ataques = tail . ataques $peleador }
| otherwise = peleador
{-----------------------------------------------------------------------------------------------------
d . Escribir el código con el que crearía a Bruce Lee, un peleador con 200 de vida y 25 de
resistencia que tiene entre sus ataques el toque de la muerte, un golpe de intensidad 500 y
un ataque más que consiste en una secuencia de tres patadas a la carita.
-----------------------------------------------------------------------------------------------------}
bruceLee :: Peleador
bruceLee = Peleador {
vida = 200,
resistencia = 25,
ataques = [toqueDeLaMuerte,
golpe 500,
patada "carita" . patada "carita" . patada "carita"]
}
{-----------------------------------------------------------------------------------------------------
2) Dados un peleador y un enemigo, encontrar el mejor ataque del peleador contra ese
enemigo (es decir, encontrar el ataque del peleador que deja con menos vida al enemigo)
-----------------------------------------------------------------------------------------------------}
mejorAtaque :: Peleador -> Peleador -> Ataque
mejorAtaque peleador oponente =
foldl1 (ataqueMasDañino oponente) . ataques $peleador
ataqueMasDañino :: Peleador -> Ataque -> Ataque -> Ataque
ataqueMasDañino peleador ataque1 ataque2
| (vida . ataque1 $peleador) < (vida . ataque2 $peleador) = ataque1
| otherwise = ataque2
{-----------------------------------------------------------------------------------------------------
Implementar las siguientes operaciones tratando de aprovechar al máximo los conceptos de
orden superior, composición y aplicación parcial:
-----------------------------------------------------------------------------------------------------}
{-----------------------------------------------------------------------------------------------------
a. terrible: un ataque es terrible para un conjunto de enemigos si, luego de realizarlo
contra todos ellos, quedan vivos menos de la mitad.
-----------------------------------------------------------------------------------------------------}
terrible :: Ataque -> [Peleador] -> Bool
terrible ataque enemigos =
(length enemigos `div` 2 > ) . length . filter (not . estaMuerto) . map ataque $enemigos
{-----------------------------------------------------------------------------------------------------
b. peligroso: un peleador es peligroso para un conjunto de enemigos si todos sus ataques son
terribles para los miembros del conjunto que son hábiles.
-----------------------------------------------------------------------------------------------------}
peligroso :: Peleador -> [Peleador] -> Bool
peligroso peleador enemigos =
all (flip terrible (filter esHabil enemigos)) . ataques $peleador
{-----------------------------------------------------------------------------------------------------
c. invencible: un peleador es invencible para un conjunto de enemigos si, luego de recibir
el mejor ataque de cada uno de ellos, sigue teniendo la misma vida que antes de ser atacado.
(No importa el orden en que se apliquen los ataques).
-----------------------------------------------------------------------------------------------------}
invencible :: Peleador -> [Peleador] -> Bool
invencible peleador =
(vida peleador == ) . vida . foldr ($) peleador . map (flip mejorAtaque peleador)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment