// lab10.cpp  (c) 2000 adolfo@di-mare.com

/** \file  lab10.cpp
    \brief Este programa implementa y usa la clase Bolsa para contar números.
    - La implementación se hace usando una lista con punteros.

    \author Adolfo Di Mare <adolfo@di-mare.com>
    \date   2000
*/

#include <iostream> // #include <iostream.h>
#include <climits>
#include <bool.h>

class ostream;

/// Contenedor de números enteros no repetidos.
class Bolsa {
    class nodo {
        nodo *next;   ///< Apuntador al siguiente nodo
        long  m_val;  ///< Valor almacenado en el nodo
        int   m_cont; ///< Cantidad de veces que \c "m_val" está en la bolsa
        friend class Bolsa;
    }; // nodo
public:
    Bolsa() : m_prm(0) {} ///< Constructor por defecto
    int  Esta(long n); // # de veces que "i" Está() en la Bolsa
    void Agrega(long i);   // incrementa "Esta(i)"
    void Graba(ostream&);  // graba todos los valores
private:
    nodo *m_prm; ///< Primer nodo de la lista
}; // Bolsa


/// Agrega el valor \c "n" a la bolsa.
/// - Si ya estaba, se incremente en uno el valor que \c "Esta()" retorna.
void Bolsa::Agrega(long n) {
    Bolsa::nodo *p, *q;  // "q" va detrás de "p"
    p = m_prm;  // p = this->m_prm;

    // recorre la lista para encontrar el valor "n"
    while ( p != 0 ) {
        q = p;  // recuerda el anterior

        if (n == p->m_val) { // lo encontró
            (p->m_cont)++;
            return;
        }
        p = p->next;
    }

    // crea un nuevo nodo para "n"
    Bolsa::nodo *nuevo = new Bolsa::nodo;
    nuevo->m_val  = n;
    nuevo->m_cont = 1;
    nuevo->next = 0;

    // enlaza el nodo
    if (m_prm == 0) {
        m_prm = nuevo; // agrega el primer nodo de la lista
    }
    else {
        q->next = nuevo;  // conecta después del último nodo
    }
    return;
} // Bolsa::Agrega()


/// Retorna la cantidad de veces que el valor \c "n" ha sido agregado a la bolsa.
/// - Retorna cero si \c "n" nunca ha sido agregado.
int Bolsa::Esta(long n) {
    Bolsa::nodo *p;  // "p" recorre la lista
    p = this->m_prm;  // p = m_prm;

    // recorre la lista para encontrar el valor "n"
    while (p !=0) {
        if (n == p->m_val) { // lo encontró
            return p->m_cont;
        }
        p = p->next;
    }
    return 0;
} // Bolsa::Esta()


/// Graba en el flujo de salida \c "COUT" todos los valores almacenados en la bolsa.
/// - Graba los valores en orden creciente.
void Bolsa::Graba(ostream& COUT) {
    for (long n=0; n<LONG_MAX; ++n) {
        if (0 != Esta(n)) {
            COUT << n << " está " << Esta(n);
            COUT << " veces en al bolsa" << endl;
        }
    }
} // Bolsa::Graba()

/// Programa principal.
int main() {
    Bolsa B;
    long  n;

    // lee todos los valores
    while (cin >> n) {
        B.Agrega(n);
    }

    // despliega los valores
    B.Graba(cout);

    return 0;
} // main()

// EOF: lab10.cpp