Data Structures

Práctica #1: DinoSets

Objetivo

Durante esta actividad, los alumnos serán capaces de:


Descripción

Tu buen amigo paleontólogo, Alan Grant, te ha pedido que implementes una clase en C++ que permita manejar conjuntos de dinosaurios (DinoSets) con el fin de desarrollar un proyecto para el control de fósiles de especies de saurios encontrados en diferentes localidades en donde están realizado escavaciones.

Un conjunto es una colección de elementos bien definidos sin repeticiones. Un DinoSet se puede implementar utilizando un arreglo de booleanos de un tamaño igual a la cantidad de especies de dinosaurios a representar. Cada localidad del arreglo representa la presencia o ausencia de una especie de dinosaurio dentro del DinoSet.

Las especies particulares de dinosaurios que se requieren en tu clase DinoSet se puede reperesentar como una enumeración de C++:

enum class DinoId {
    velocirraptor,      // 0
    estegosaurio,       // 1
    tiranosaurio,       // 2
    procompsagnatus,    // 3
    triceratops,        // 4
    paquicefalosaurio,  // 5
    parasaurolofus,     // 6
    pteranodon          // 7
};

El número entero en los comentarios del código anterior corresponde a un índice dentro del arreglo de booleanos. Entonces, por ejemplo, si la localidad 0 del arreglo vale true, quiere decir que el conjunto contiene al velocirraptor. En caso de que la localidad 0 del arreglo sea igual a false, entonces el conjunto no contiene al velocirraptor. La enumeración DinoId permite referirse a los dinosaurios por nombre en lugar de número, es decir, en lugar de referirse al dinosaurio 1, se debe uno referir al dinosaurio DinoId::estegosaurio, lo cual facilita la legibilidad del programa.

Las funciones miembro de la clase DinoSet se describen a continuación:

Función Descripción
void add(DinoId) Agrega al objeto receptor el elemento indicado por el DinoId de entrada.
void remove(DinoId) Elimina del objeto receptor el elemento indicado por el DinoId de entrada.
bool contains(DinoId) const Regresa true si el DinoId que toma como entrada representa un elemento contenido en el objeto receptor, o false en caso contrario.
int size() const Regresa el número de elementos contenidos en el objeto receptor.
bool is_empty() const Regresa true si el objeto receptor es un conjunto vacío (tiene cero elementos), o false de otra forma.
DinoSet operator+(
    const DinoSet&
) const
Unión: devuelve un nuevo DinoSet conformado por todos los elementos contenidos en el objeto receptor y/o en el DinoSet que se recibe como entrada.
DinoSet operator*(
    const DinoSet&
) const
Intersección: devuelve un nuevo DinoSet conformado por todos los elementos contenidos en el objeto receptor y en el DinoSet que se recibe como entrada.
DinoSet operator-(
    const DinoSet&
) const
Diferencia: devuelve un nuevo DinoSet conformado por todos los elementos contenidos en el objeto receptor pero que no están contenidos en el DinoSet que se recibe como entrada.
DinoSet operator!() const Complemento: devuelve un nuevo DinoSet conformado por todos aquellos elementos que no pertenecen al objeto receptor.
bool operator==(
    const DinoSet&
) const
Regresa true si la entrada contiene exactamente los mismos elementos que el objeto receptor. En otro caso regresa false.
std::string to_string() const Devuelve la representación del objeto receptor como una cadena de caracteres. Ver ejemplos más adelante para conocer el formato preciso.

Coloca todo tu código en un archivo llamado dinoset.h. Prueba tu implementación de la clase con las siguientes pruebas unitarias (contiene 93 aserciones en total):

#include "catch.hpp"
#include "dinoset.h"

TEST_CASE("test the DinoSet class")
{
    DinoSet a;

    DinoSet b;
    b.add(DinoId::velocirraptor);
    b.add(DinoId::tiranosaurio);

    DinoSet c;
    c.add(DinoId::tiranosaurio);
    c.add(DinoId::procompsagnatus);
    c.add(DinoId::pteranodon);

    SECTION("test to_string") {
        REQUIRE(a.to_string() == "{}");
        REQUIRE(b.to_string() == "{velocirraptor, tiranosaurio}");
        REQUIRE(c.to_string()
            == "{tiranosaurio, procompsagnatus, pteranodon}");
    }

    SECTION("test contains") {
        REQUIRE_FALSE(a.contains(DinoId::velocirraptor));
        REQUIRE_FALSE(a.contains(DinoId::estegosaurio));
        REQUIRE_FALSE(a.contains(DinoId::tiranosaurio));
        REQUIRE_FALSE(a.contains(DinoId::procompsagnatus));
        REQUIRE_FALSE(a.contains(DinoId::triceratops));
        REQUIRE_FALSE(a.contains(DinoId::paquicefalosaurio));
        REQUIRE_FALSE(a.contains(DinoId::parasaurolofus));
        REQUIRE_FALSE(a.contains(DinoId::pteranodon));

        REQUIRE(b.contains(DinoId::velocirraptor));
        REQUIRE_FALSE(b.contains(DinoId::estegosaurio));
        REQUIRE(b.contains(DinoId::tiranosaurio));
        REQUIRE_FALSE(b.contains(DinoId::procompsagnatus));
        REQUIRE_FALSE(b.contains(DinoId::triceratops));
        REQUIRE_FALSE(b.contains(DinoId::paquicefalosaurio));
        REQUIRE_FALSE(b.contains(DinoId::parasaurolofus));
        REQUIRE_FALSE(b.contains(DinoId::pteranodon));

        REQUIRE_FALSE(c.contains(DinoId::velocirraptor));
        REQUIRE_FALSE(c.contains(DinoId::estegosaurio));
        REQUIRE(c.contains(DinoId::tiranosaurio));
        REQUIRE(c.contains(DinoId::procompsagnatus));
        REQUIRE_FALSE(c.contains(DinoId::triceratops));
        REQUIRE_FALSE(c.contains(DinoId::paquicefalosaurio));
        REQUIRE_FALSE(c.contains(DinoId::parasaurolofus));
        REQUIRE(c.contains(DinoId::pteranodon));
    }

    SECTION("test size") {
        REQUIRE(a.size() == 0);
        REQUIRE(b.size() == 2);
        REQUIRE(c.size() == 3);
    }

    SECTION("test is_empty") {
        REQUIRE(a.is_empty());
        REQUIRE_FALSE(b.is_empty());
        REQUIRE_FALSE(c.is_empty());
    }

    SECTION("test remove") {
        REQUIRE(c.size() == 3);
        REQUIRE(c.contains(DinoId::procompsagnatus));
        c.remove(DinoId::procompsagnatus);
        REQUIRE(c.size() == 2);
        REQUIRE_FALSE(c.contains(DinoId::procompsagnatus));
        REQUIRE(c.to_string() == "{tiranosaurio, pteranodon}");
        REQUIRE(c.contains(DinoId::tiranosaurio));
        c.remove(DinoId::tiranosaurio);
        REQUIRE(c.size() == 1);
        REQUIRE_FALSE(c.contains(DinoId::tiranosaurio));
        REQUIRE(c.to_string() == "{pteranodon}");
        REQUIRE(c.contains(DinoId::pteranodon));
        c.remove(DinoId::pteranodon);
        REQUIRE(c.is_empty());
        REQUIRE_FALSE(c.contains(DinoId::pteranodon));
        REQUIRE(c.to_string() == "{}");

        REQUIRE(b.size() == 2);
        REQUIRE(b.contains(DinoId::tiranosaurio));
        b.remove(DinoId::tiranosaurio);
        REQUIRE(b.size() == 1);
        REQUIRE_FALSE(b.contains(DinoId::tiranosaurio));
        REQUIRE(b.to_string() == "{velocirraptor}");
        REQUIRE(b.contains(DinoId::velocirraptor));
        b.remove(DinoId::velocirraptor);
        REQUIRE(b.is_empty());
        REQUIRE_FALSE(b.contains(DinoId::velocirraptor));
        REQUIRE(b.to_string() == "{}");

        REQUIRE(a.is_empty());
        REQUIRE_FALSE(a.contains(DinoId::tiranosaurio));
        a.remove(DinoId::tiranosaurio);
        REQUIRE(a.is_empty());
        REQUIRE_FALSE(a.contains(DinoId::tiranosaurio));
        REQUIRE(a.to_string() == "{}");
        REQUIRE_FALSE(a.contains(DinoId::pteranodon));
        a.remove(DinoId::pteranodon);
        REQUIRE(a.is_empty());
        REQUIRE_FALSE(a.contains(DinoId::pteranodon));
        REQUIRE(a.to_string() == "{}");
    }

    SECTION("test +") {
        REQUIRE((a + b).to_string()
            == "{velocirraptor, tiranosaurio}");
        REQUIRE((a + c).to_string()
            == "{tiranosaurio, procompsagnatus, pteranodon}");
        REQUIRE((b + c).to_string()
            == "{velocirraptor, tiranosaurio, procompsagnatus, "
               "pteranodon}");
        REQUIRE((c + b).to_string()
            == "{velocirraptor, tiranosaurio, procompsagnatus, "
               "pteranodon}");
    }

    SECTION("test *") {
        REQUIRE((a * b).to_string() == "{}");
        REQUIRE((a * c).to_string() == "{}");
        REQUIRE((b * c).to_string() == "{tiranosaurio}");
        REQUIRE((c * b).to_string() == "{tiranosaurio}");
    }

    SECTION("test -") {
        REQUIRE((a - b).to_string() == "{}");
        REQUIRE((b - a).to_string()
            == "{velocirraptor, tiranosaurio}");
        REQUIRE((a - c).to_string() == "{}");
        REQUIRE((c - a).to_string()
            == "{tiranosaurio, procompsagnatus, pteranodon}");
        REQUIRE((b - c).to_string() == "{velocirraptor}");
        REQUIRE((c - b).to_string()
            == "{procompsagnatus, pteranodon}");
    }

    SECTION("test !")
    {
        REQUIRE((!a).to_string()
            == "{velocirraptor, estegosaurio, tiranosaurio, "
               "procompsagnatus, triceratops, paquicefalosaurio, "
               "parasaurolofus, pteranodon}");
        REQUIRE((!b).to_string()
            == "{estegosaurio, procompsagnatus, triceratops, "
               "paquicefalosaurio, parasaurolofus, pteranodon}");
        REQUIRE((!c).to_string()
            == "{velocirraptor, estegosaurio, triceratops, "
               "paquicefalosaurio, parasaurolofus}");
    }

    SECTION("test ==") {
        DinoSet x;

        DinoSet y;
        y.add(DinoId::tiranosaurio);
        y.add(DinoId::velocirraptor);

        DinoSet z;
        z.add(DinoId::procompsagnatus);
        z.add(DinoId::pteranodon);
        z.add(DinoId::tiranosaurio);

        REQUIRE(a == a);
        REQUIRE(a == x);
        REQUIRE_FALSE(a == y);
        REQUIRE_FALSE(a == z);

        REQUIRE(b == b);
        REQUIRE_FALSE(b == x);
        REQUIRE(b == y);
        REQUIRE_FALSE(b == z);

        REQUIRE(c == c);
        REQUIRE_FALSE(c == x);
        REQUIRE_FALSE(c == y);
        REQUIRE(c == z);
    }
}

¿Qué se debe entregar?

Coloca en un comentario en la parte superior del archivo fuente dinoset.h la información personal de los autores (matrícula y nombre), por ejemplo:

/*----------------------------------------------------------
 * Práctica #1: DinoSets
 * Implementación de la clase DinoSet.
 *
 * Fecha: 27-Ago-2021
 * Autores:
 *           A01770771 Sylvie Laufeydottir
 *           A01777771 Loki Laufeyson
 *----------------------------------------------------------*/

Upload Instructions

To deliver the dinoset.h file, please provide the following information:

Request PIN

Solo es necesario que lo entregue un miembro del equipo.

La fecha límite es el viernes 27 de agosto.