[C con Clase] (sin asunto)

Manuel L. notret en gmx.es
Jue Sep 16 12:30:22 CEST 2010


Aunque ya se ha dado una solución, planteo otra forma de resolverlo utilizando números aleatorios. El algoritmo consiste en tomar aleatoriamente una secuencia de números de tal modo que no se sobrepase la suma. Para ello, basta con escoger números comprendidos enre el cero y el mínimo entre el mayor número posible para la secuencia y lo que resta para sumar el número pedido. En caso de que la suma de los números obtenidos sea inferior se reparte aleatoriamente lo que falta entre los distintos números.

La solución realemnte está en la clase "ClaseGeneradora", aunque le hice una pequeña interfaz textual de ejemplo. Escribo a continuación una posible implementación:


   ###############################
   #                             #
   # Archivo "claseGeneradora.h" #
   #                             #
   ###############################


#ifndef CLASE_GENERADORA_H
#define CLASE_GENERADORA_H

#include <vector>
   using std::vector;
#include <stdexcept>
   using std::invalid_argument;

class ClaseGeneradora
{

public:
   // MANIPULACION DE OBJETOS
   ClaseGeneradora(int noNumeros = 20,int maxNoAleatorio = 180,int suma = 500) throw(invalid_argument);
   ~ClaseGeneradora();

   // METODOS
   void establecerNoNumeros(int noNumeros) throw(invalid_argument);
   void establecerMaxNoAleatorio(int maxNoAleatorio) throw(invalid_argument);
   void establecerSuma(int suma) throw(invalid_argument);
   inline int verNoNumeros() const;
   inline int verMaxNoAleatorio() const;
   inline int verSuma() const;
   void obtenerSecuencia(vector<int> &l) const;

private:
   // ATRIBUTOS
   int noNumeros,maxNoAleatorio,suma;

};

#endif


   #################################
   #                               #
   # Archivo "claseGeneradora.cpp" #
   #                               #
   #################################

#include <string>
   using std::string;
#include <algorithm>
   using std::min;
#include <cstdlib>
#include "claseGeneradora.h"

ClaseGeneradora::ClaseGeneradora(int noNumeros,int maxNoAleatorio,int suma) throw(invalid_argument)
               : noNumeros(noNumeros),maxNoAleatorio(maxNoAleatorio),suma(suma)
   {

   string error("ClaseGeneradora::ClaseGeneradora : ");

   if(noNumeros < 1) throw invalid_argument(error + "noNumeros < 1");
   if(maxNoAleatorio < 1) throw invalid_argument(error + "maxNoAleatorio < 1");
   if(suma < 0) throw invalid_argument(error + "suma < 0");

   }


ClaseGeneradora::~ClaseGeneradora() {}


void ClaseGeneradora::establecerNoNumeros(int noNumeros) throw(invalid_argument)
   {

   if(noNumeros < 1) throw invalid_argument("ClaseGeneradora::establecerNoNumeros : noNUmeros < 1");

   this->noNumeros = noNumeros;

   }


void ClaseGeneradora::establecerMaxNoAleatorio(int maxNoAleatorio) throw(invalid_argument)
   {

   if(maxNoAleatorio < 1) throw invalid_argument("ClaseGeneradora::establecerMaxNoAleatorio : maxNoAleatorio < 1");

   this->maxNoAleatorio = maxNoAleatorio;

   }


void ClaseGeneradora::establecerSuma(int suma) throw(invalid_argument)
   {

   if(suma < 0) throw invalid_argument("ClaseGeneradora::establecerSuma : suma < 0");

   this->suma = suma;

   }


int ClaseGeneradora::verNoNumeros() const { return noNumeros; }


int ClaseGeneradora::verMaxNoAleatorio() const { return maxNoAleatorio; }


int ClaseGeneradora::verSuma() const { return suma; }


void ClaseGeneradora::obtenerSecuencia(vector<int> &l) const
   {

   l.clear(); // Por si tuviese algun elemento
   int aRepartir = suma; // Cantidad a repartir entre "noNumeros" numeros

   // Obteniendo 20 numeros aleatorios cuya suma sea menor o igual a "suma"
   srand(time(0)); // semilla 'aleatoria'
   for(int i=noNumeros;i;--i)
      {
      int nuevoNo = (int) ( random() % (1+min(maxNoAleatorio,aRepartir)) );
      aRepartir-= nuevoNo;
      l.push_back(nuevoNo);
      }

   // Repartiendo lo que no se haya adjudicado aleatoriamente entre los elementos
   while(aRepartir)
      {
      int incremento = random() % aRepartir;
      aRepartir-= ++incremento;
      l[random() % noNumeros]+= incremento;
      }

   }


   ##########################
   #                        #
   # Archivo "pricipal.cpp" #
   #                        #
   ##########################



#include <iostream>
	using std::cout;
#include <algorithm>
	using std::sort;
#include "claseGeneradora.h"


int main()
   {

   vector<int> l;
   ClaseGeneradora().obtenerSecuencia(l);
   sort(l.begin(),l.end()); // Motivos esteticos

   cout << "\n\nUna posible lista es la siguiente:\n";
   vector<int>::const_iterator pL = l.begin(),finL = l.end();
   for(;pL != finL;++pL) cout << "  " << *pL << "\n";
   cout << "\n\n";

   return 0;

   }


Más información sobre la lista de distribución Cconclase