Datos personales

domingo, 29 de abril de 2012

Cálculo de número de combinaciones sin/con repeticiones de n en k



/* ******************************************************************************
 * Autor:          Marlene E.Vásquez C
 * Descripción:    Programa que realiza el cálculo de número de combinaciones,
 *                 sin repeticiones y con repetición de n en k.
 * Fecha:          22-12 2011
 *********************************************************************************/

/**
* @file combinaciones.cpp
* @brief Programa que realiza el cálculo de número de combinaciones,
* sin repetición y con repetición, de n en k.
*
* El programa pide un par de valores positivos y el segundo no debe ser mayor.
*
* Salida: escribir el número de combinaciones de n en k, con repeticiones y sin
* repeticiones.
*/

#include <iostream> // biblioteca para uso de cout
#include <cmath>//utilizar sqrt
#include <vector>  //Para utilizar vectores
using namespace std;
// Funciones
void leerDatos(int &m,int &p);
bool EsPrimo(int n);//
bool esCalculable(vector <int> x,int &p);
vector <int> FactoresPrimos(int numero);
vector <int> ProductoComponentes(vector <int> v, vector <int> c);
vector <int> Factorial(int numero);
vector <int> eliminarElementos(vector<int> v) ;// funcion necesaria para la funcion Simplificar Nº2 comentada.

void Simplificar(vector <int> &primosNumerador,vector <int> &primosDenominador);
void Producto(vector <int> v);
void imprimirVector(vector <int> v);

void CombinacionesConRepeticiones(int n , int k);
void CombinacionesSinRepeticiones(int n , int k);
void C(int m , int p);

int main()
{
    cout << "------ Programa de Cálculo de Combinaciones ------" << endl;
    int m, p ;
    leerDatos(m,p);

    C(m,p);
}
/**
 * @brief lee dos valores
 * @param n  primer parametro pasado por referencia.
 * @param k  segundo parametro pasado por referencia.
 * @pre carga @a n y @a k  > 0 y @a k es menor que @a n
 */
void leerDatos( int &n , int &k )
{
    cout << "Introduzca n y k : ";
    cin >> n >> k ;
    while (n<0 || k<0 || k>n)
    {
        cout << "No puede ser negativo y el segundo no puede ser mayor"<<endl;
        cout << "Introduzca de nuevo: ";
        cin >> n >> k;
    }
}
/**
 * @brief
 * @param n
 * @return si es primo.
 */
bool EsPrimo( int n )
{
    int raiz = sqrt(n);
    bool esprimo = true;
    for(int i = 2; i <= raiz && esprimo; ++i)
    {
        if(n%i == 0)
            esprimo = false;//es divisible
    }
    return esprimo;
}
/**
 * @brief Módulo para calcular la descomposición en factores primos. Este módulo 
 * convierte un
 * valor entero (int) a un vector con la descomposición en números primos.
 * @param numero
 * @return @a primos vector con los factores primos de @a numero
 */
vector <int> FactoresPrimos( int numero )
{
    vector <int> primos;
    int i = 2;
    if ( EsPrimo(numero)== false)
    {
        do
        {
            if (!(numero % i))
            {
                numero = numero / i;
                primos.push_back(i);
            }
            else
                i++;
        }while(i <= numero);
     }
     else
        primos.push_back(numero);
    return primos;
}
/**
 * @brief Módulo para multiplicar “enteros”. Obtiene el vector resultado de 
 * multiplicar dos
 * vectores que corresponden a descomposiciones de números en primos.
 * @param a primer "vector" parametro.
 * @param b segundo "vector" parametro.
 * @return @a c vector resultante de unir los vectores v y c.
 */
vector <int> ProductoComponentes(vector <int> a ,vector <int> b)
{
    vector<int> c;

    int i= 0,j= 0;

    while( i < a.size() && j  < b.size())
    {
        if(a.at(i) < b.at(j))
        {
            c.push_back(a.at(i));
            i++;
        }
             else
             {
                 c.push_back(b.at(j));
                 j++;
             }
    }
    if (i < a.size())
    {
       while(i < a.size())
       {
           c.push_back(a.at(i));
           ++i;
       }
    }
    if(j<b.size())
    {
       while(j < b.size())
       {
           c.push_back(b.at(j));
           j++;
       }
    return c;
}
}
/**
* @brief Módulo para calcular el factorial. realiza el calculo factorial de un 
* numero.
* @param numero
* @return @a nuevo vector que contiene el factorial de @a numero descompuesto en 
* factores primos .
*/
vector <int> Factorial(int numero)
{
    vector <int> nuevo;
    for (int i=2; i<=numero ; ++i)
    {
        nuevo = ProductoComponentes(nuevo,FactoresPrimos(i));
    }
    return nuevo;
}
/**
 * @brief  Módulo para determinar  si el entero es calculable.
 * @param  v "vector".
 * @return si es calculable .
 */
bool esCalculable(vector <int> v,int &p)
{
    int u = 1,n;
    bool calc = false;
    for ( int i=0;i<v.size(); ++i )
    {
        n = u * v.at(i);
        if (i == v.size()-1 && n/v.at(i) == u )
        {
            calc = true;
            p=n;
        }
        else
        if( n/v.at(i) != u)
        {
                calc = false;
                break;
        }
        u = n ;
    }
    return calc;
}
/**
* @brief Módulo para dividir enteros. Obtiene el vector resultado de dividir dos * vectores que corresponden a descomposiciones de números en primos. Dado que el * resultado no tiene por qué ser un entero, este modulo esta implementado para 
* que transforme el numerador y el denominador mediante la simplificación 
* "eliminacion" de primos comunes.
* @param primosNumerador "vector" primer argumento pasado por referencia. 
* @param primosDenominador "vector" segundo argumento pasado por referencia. */
//----------------------Funciones para simplificar------------------------

//------------------------Funcion Simplificar---------------------------
void Simplificar(vector <int> &primosNumerador, vector <int> &primosDenominador)
{
    int i=0,j=0;
    vector<int> numerador;
    vector<int> denominador;
    while( i < primosNumerador.size() && j  < primosDenominador.size())
    {
        if(primosNumerador.at(i) < primosDenominador.at(j))
        {
            numerador.push_back(primosNumerador.at(i));
            i++;
        }
             else if (primosNumerador.at(i) == primosDenominador.at(j))
             {
                i++;
                j++;
             }else if(primosNumerador.at(i) > primosDenominador.at(j))
             {
                denominador.push_back(primosDenominador.at(j));
                j++;
             }
    }
    if (i<primosNumerador.size())
    {
       while(i < primosNumerador.size())
       {
           numerador.push_back(primosNumerador.at(i));
           i++;
       }
    }
    if(j < primosDenominador.size())
    {
       while(j < primosDenominador.size())
       {
           denominador.push_back(primosDenominador.at(j));
           j++;
       }
    }
    if(numerador.empty())   numerador.push_back(1);
    if(denominador.empty()) denominador.push_back(1);

    primosNumerador=numerador;
    primosDenominador=denominador;
}
//------------------------Funcion Simplificar Nº2----------------------------

//void Simplificar(vector <int> &primosNumerador, vector <int> &primosDenominador)
//{

//         // Elimina de cada vector los factores primos repetidos
//
//         // reemplazandolos por 1
//         for(int i=0;i < primosNumerador.size();++i)
//         {
//             for (int j=0;j < primosDenominador.size();++j)
//             {
//                 if (primosNumerador.at(i) == primosDenominador.at(j))
//                 {
//                     primosNumerador.at(i) = 1;
//                     primosDenominador.at(j) = 1;
//                 }
//             }
//         }
//
//        primosNumerador= eliminarElementos(primosNumerador);
//        primosDenominador=eliminarElementos(primosDenominador);
//}
// /**
// * @brief  Módulo para eliminar elementos del vector que sean igual a 1
// * @param  v "vector".
// * @return resultado "vector" con elementos !=1
// */
//vector <int> eliminarElementos(vector<int> v)
//{
//    vector<int> resultado;
//    for (int i=0; i<v.size();++i)
//    {
//        if (v.at(i)!=1)// si el valor del vector es diferente de 1 se escribe en el vector resultado
//            resultado.push_back(v.at(i));
//    }
//    if (resultado.empty())// si el vector resultado es vacio
//        resultado.push_back(1);
//
//    return resultado;
//}
//------------------------------------------------------------------------------------------------------------------
/**
 * @brief  Módulo para calcular el producto de los elemento de un vector
 * @param  v "vector".
 * @post  esCalculable(v)==true;
 *
 */
void Producto(vector <int> v)
{
    int p;
    if((esCalculable(v,p) == false))// llama a la funcion esCalculable();
       cout <<" = Entero Indeterminado" << endl;
    else
        if (p !=1 )
            cout << " = "<< p << endl;
        else
            cout << endl;

}

/**
 * @brief  Módulo para mostrar datos que contiene un vector y
 * el resultado de multiplicar cada uno de sus elementos.
 *
 * @param  v "vector".
 */
void imprimirVector(vector <int> v)
{
    int i=0, m=v.size();
    while(i < m)
    {
        if(i < m-1)
            cout <<  v.at(i) << " * ";
        else
            cout <<  v.at(i);
        ++i;
    }
    Producto(v);
}
/**
 * @brief  Módulo para calcular la ecuacion c = n! / k!*(n-k)!
 *
 * @param  n primer parametro
 * @param  k segundo parametro
 */
void CombinacionesSinRepeticiones(int n, int k)
{
    //(El numero combinatorio n sobre k calculado de la forma:
  /*
                             n         n!          -> numerador
                    c(n,k)=(    )=(----------- )
                             k      k!*(n-k)!      -> denominador
  */
    vector <int> numerador;
    vector <int> denominador;
    numerador   = Factorial(n);
    denominador = ProductoComponentes(Factorial(k),Factorial(n-k));

    cout << "Combinaciones sin repeticiones de n en k" <<endl;
    Simplificar(numerador,denominador);
    cout << "Numerador: ";
    imprimirVector(numerador);
    cout << "Denominador: ";
    imprimirVector(denominador);

}
/**
 * @brief  Módulo para calcular la ecuacion c = (n+k-1)! / k!*(n-1)!
 *
 * @param  n primer parametro
 * @param  k segundo parametro
 */
void CombinacionesConRepeticiones(int n, int k)
{
    //(El numero combinatorio n sobre k calculado de la   :
  /*
                                 n+k-1     (n+k-1)!       -> numerador
                    c(n+k-1,k)=(       )= -----------
                                   k       k!*(n-1)!      -> denominador
  */
    vector <int> numerador;
    vector <int> denominador;

    numerador   = Factorial(n+k-1);
    denominador = ProductoComponentes(Factorial(k),Factorial(n-1));

    cout << "Combinaciones con repeticiones de n en k" << endl;
    Simplificar(numerador,denominador);
    cout << "Numerador: ";
    imprimirVector(numerador);
    cout << "Denominador: ";
    imprimirVector(denominador);

}

/**
 * @brief  Módulo que simplifica la llamada a las dos funciones
 * que calculan la ecuaciones  y presentan los resultados de las dos ecuaciones
 * calculadas independientemente.
 * @param  m primer parametro
 * @param  p segundo parametro
 */

void C(int m, int p)
{
    CombinacionesSinRepeticiones(m,p);

    cout << "-----------------------" << endl;

    CombinacionesConRepeticiones(m,p);
}

No hay comentarios:

Publicar un comentario