Cursos‎ > ‎Sábados Mañana - Anual‎ > ‎

TP3 Funcional

Plantas Vs.  Zombies

 

En todo jardín nos encontramos con una situación en común: el ataque de los zombies. Es nuestro deber defender nuestros hogares de estos comedores de cerebros.

La forma mas efectiva de repeler el ataque de zombies, claro está, es con plantas, como todos sabemos.
Para afrontar la situación en nuestros jardines se necesita de la codificación de un programa Haskell que modele esta problemática.
 

Primero debemos saber que las plantas se modelan con una 5-upla con los siguientes datos: (cantidad de disparos, cantidad de mordisco que se banca, soles que da, daño, frecuencia de acción). Por ejemplo:


peaShooter = (1,5,0,10,3)
sunflower = (0,7,1,0,6)
nut = (0,100,0,0,0)
puffShroom = (5,1,0,1,1)


Para que sea mas fácil de acceder, nuestro vecino “Crazy Dave” nos regaló estas funciones:


cantidadDeDisparos(d,_,_,_,_) = d

cantidadDeMordiscos(_,m,_,_,_) = m
cantidadDeSoles(_,_,s,_,_) = s
daño(_,_,_,d,_) = d
frecuencia (_,_,_,_,f) = f



Para defendernos de los ataques zombies, se plantean líneas de defensa, cada línea es una lista de plantas, por ejemplo podríamos plantear las siguientes líneas:


linea1 = [sunflower,sunflower,sunflower,sunflower]
linea2 = [sunflower,peaShooter,peaShooter,sunflower]
linea3 = [puffShroom,puffShroom,puffShroom,peaShooter]
linea4 = [nut,puffShroom,puffShroom,nut]

Puede venir bien recordar las siguientes funciones del prelude:

  • head --> devuelve la cabeza de una lista
  • tail --> devuelve la cola de una lista (complemento de head)
  • last --> devuelve el último elemento de una lista
  • init --> devuelve la lista desde el primero hasta el penúltimo elemento de una lista (complemento de last)
  • div --> división entera

Nota: Se debe aplicar, en el desarrollo de los distintos puntos, al menos una vez cada uno de los siguientes conceptos:
  • Listas por comprensión
  • Recursividad
  • Orden superior
  • Composición de funciones
  • Pattern matching
  • Aplicación parcial

Se pide:

  1. Poder determinar de qué especialidad es una planta. Tener en cuenta para esto que:
    1. Las plantas que dan soles son de especialidad “Proveedora”
    2. Las plantas cuyo daño potencial (que se calcula como la cantidad de disparos multiplicado por su daño) es  mayor o igual que la cantidad de mordiscos que se banca, son de especialidad “Ataque”.
    3. Si no cumplen con ninguna de las anteriores son de especialidad “Defensa”.

      Por ejemplo:


      > especialidad peaShooter
      “Proveedora”


  2. Poder determinar si una línea necesita ser defendida, esto pasa cuando todas las plantas de esa linea son proveedoras. Por ejemplo:

    > necesitaSerDefendida linea1
    True


    > necesitaSerDefendida linea3

    False



    1. Poder saber la potencia de ataque que tiene una planta, que se calcula como: la cantidad de disparos multiplicada por el daño dividido por la frecuencia (división entera) (si la frecuencia es 0, su potencia también lo es). Por ejemplo:

      > potencia nut
      0

      > potencia puffShroom
      5

    2. Saber la potencia total de una línea de plantas.

      > potenciaTotal linea4
      10


  3. a) Realizar una función que reciba dos parámetros:
                   1- una condición sobre una planta
                   2- una lista de plantas
    y devuelva un numero, que representa la cantidad de plantas de esa linea que cumplen con esa condición.
    b) Realizar las consultas (
    sin codificar funciones auxiliares) que permitan saber:
    1. La cantidad de plantas que dan al menos un sol en la linea1
    2. La cantidad de plantas que tienen potencia de ataque mayor a 3 en la linea2
    3. La cantidad de plantas que se bancan más de 5 mordiscos en la linea2
    4. La cantidad de plantas para las cuales el daño menos la frecuencia da un número par en linea3

  4. Saber si una línea es mixta, que es cuando ninguna de las plantas de la línea tiene la misma especialidad que su inmediata siguiente. Además, la línea debe tener al menos dos plantas.
    Nota: No usar length (ni ninguna función que tenga el mismo propósito).

    > lineaMixta linea2
    False


    Ahora se agregan (¡finalmente!) los zombies, que se representan por tuplas (mordiscosPorTurno, defensa).

    balloonZombie = (1, 11)
    newspaperZombie = (2, 16)
    gargantuar = (30, 150)

    Y las hordas de zombies correspondientes:

    septimoRegimiento = [newspaperZombie, balloonZombie, balloonZombie]
    legion = [gargantuar, gargantuar, gargantuar, gargantuar, gargantuar, gargantuar]

    Para estos, tenemos las funciones:

    mordiscosPorTurno = fst
    defensa = snd

  5. Saber cómo seria el resultado de una ronda de ataque para una planta y un zombie. El resultado de esta funcion debe ser una dupla (planta, zombie) con el resultado del “fuego cruzado”, es decir, como quedarian el zombie y la planta luego de enfrentarse. Los ataques son simples:

    1. El zombie muerde a la planta tantas veces como indique su valor de mordiscosPorTurno, disminuyendo el valor de cantidadDeMordiscos en igual cantidad.

    2. La planta le baja la defensa al zombie de igual forma, según su potencia de ataque.

    En ambos casos, el valor mínimo de cantidadDeMordiscos/defensa resultante debe ser 0, en cuyo caso la planta muere o el zombie es destruido (lo cual no es relevante para esta función, pero sí más adelante).

    > rondaDeAtaque puffShroom gargantuar

    ((1,0,0,1,1), (30,145))

    El gargantuar es atacado con una potencia de 5, mientras que el puffShroom es atacado con una potencia de 30 (detalle: el puffShroom muere, pero dijimos que acá eso no afecta).


  6. Conocer el resultado de un ataque masivo en una linea de plantas. Se pide lo mismo que para la anterior (una única ronda de ataque), pero para una lista de plantas y una lista de zombies. La diferencia con la anterior es que si una planta muere o un zombie es destruido, la lista resultante no deberá incluirlos, y además se debe considerar que siempre los que pelean son la última planta contra el primer zombie.
    Ejemplo, para la consulta:

    > resultadoDeAtaque linea3 septimoRegimiento
    ([(5,1,0,1,1),(5,1,0,1,1),(5,1,0,1,1),(1,3,0,10,3)],
    [(2,13),(1,11),(1,11)])


    los que pelean son el peaShooter y el newspaperZombie.

  7. Desarrollar la función theZombiesAteYourBrains, que nos dice si, para una línea de plantas y una lista de zombies que atacan, luego de un ataque en serie de los zombies nos quedamos sin plantas. Un ataque en serie es una sucesión de ataques que termina cuando nos quedamos sin plantas (y nos comen el cerebro) o destruimos a todos los zombies. Las plantas y zombies en cada nuevo ataque son los que correspondan al resultado del ataque anterior.
    Nota: Si al mismo tiempo que nos quedamos sin plantas, también se acaban los zombies... ¡zafamos!
    Ayuda: Recursividad.

    > theZombiesAteYourBrains linea1 legion
    True



  8. Aclaración: Los puntos 1, 2 y 5 son puntos Bonus y no es obligatorio resolverlos.