Thread: Help with getting different random numbers in a vector

  1. #1
    Registered User
    Join Date
    Feb 2015
    Posts
    56

    Help with getting different random numbers in a vector

    I am making a program that "simulates" genetic breakdown in DNA and simulates population growth of a fake group of beings, what I need to do is simulate beings pairing up with male and female and mating. Each being has a name which is a number and I have a random number generator that outputs a number and that number is a name of a being both male and female and it pairs them up with each other, however I need it to pair up unique males and females, but it just pairs up the same males and females sometimes, so it's doing this:

    1 0
    1 3
    2 0
    3 2

    as you can see "1" is pairing up multiple times with 0 and 3, and that shouldn't happen. Here is my code, please forgive it, it's quite a mess, I want to get the program working before I split it up into classes and functions:

    Code:
    #include <iostream>#include <string>
    #include <fstream>
    #include <time.h>
    #include <stdlib.h>
    #include <map>
    #include <thread>
    #include <vector>
    
    
    time_t CountTime(int countTime)
    {
        double timepassed = 0.0;
        time_t start = time(NULL); //gets the number of seconds since Jan. 1 2000.
        time_t end = time(NULL);
    
    
        while(timepassed < countTime)
        {
            std::cout << timepassed << std::endl;
            end = time(NULL);
            timepassed = difftime(end, start);
            std::cout << timepassed << std::endl;
        }
    
    
        return timepassed;
    }
    
    
    int main()
    {
        int maleCurrentPopulation = 4;
        int femaleCurrentPopulation = 4;
    
    
        int beingCurrentPopulation = maleCurrentPopulation + femaleCurrentPopulation;
        int beingsThatAreDead = 0;
    
    
        int matingTime = 5;
        int gestationTime = 30;
    
    
        bool isMale = true;
        bool isFemale = true;
        bool isRelated = false;
    
    
        std::vector<std::pair<int, int> > pairBeingsUp; //pairs up one male and female.
    
    
        //Male
        std::vector<int> M_beingNames;
        std::vector<std::string> M_beingGenders;
        std::vector<int> M_cleanDna;
        std::vector<int> M_defectiveDna;
        std::vector<int> M_generation;
        std::vector<std::string> M_relationship; // son, daughter etc.
        std::vector<std::pair<int, int> > M_parentNames;
        std::vector<int> M_beingLifespan;
        std::vector<int> M_beingCurrentAge;
        std::vector<bool> M_hasMated;
        std::vector<bool> M_isOffspring;
        std::vector<bool> M_isCoupled; //Has a mate
    
    
        //Female
        std::vector<int> F_beingNames;
        std::vector<std::string> F_beingGenders;
        std::vector<int> F_cleanDna;
        std::vector<int> F_defectiveDna;
        std::vector<int> F_generation;
        std::vector<std::string> F_relationship; // son, daughter etc.
        std::vector<std::pair<int, int> > F_parentNames;
        std::vector<int> F_beingLifespan;
        std::vector<int> F_beingCurrentAge;
        std::vector<bool> F_hasMated;
        std::vector<bool> F_isOffspring;
        std::vector<bool> F_isCoupled;
    
    
        //Setup Gen 1 Beings
    
    
        //Males
        for(int i = 0; i < maleCurrentPopulation; i++)
        {
            M_beingNames.push_back(i);
            M_beingGenders.push_back("Male");
            M_cleanDna.push_back(100);
            M_defectiveDna.push_back(0);
            M_generation.push_back(1);
            M_relationship.push_back("Self");
            M_parentNames.push_back(std::make_pair(-1, -1));
            M_beingLifespan.push_back(80);
            M_beingCurrentAge.push_back(1);
            M_hasMated.push_back(false);
            M_isOffspring.push_back(false);
            M_isCoupled.push_back(false);
        }
    
    
        for(int i = 0; i < maleCurrentPopulation; i++)
        {
            std::cout << "Name: " << M_beingNames[i] << "\n";
            std::cout << "Gender: " << M_beingGenders[i] << "\n";
            std::cout << "Clean DNA%: " << M_cleanDna[i] << "\n";
            std::cout << "Defective DNA%: " << M_defectiveDna[i] << "\n";
            std::cout << "Generation: " << M_generation[i] << "\n";
            std::cout << "Relationship: " << M_relationship[i] << "\n";
            std::cout << "Parents: " << M_parentNames[i].first << " " << M_parentNames[i].second << "\n";
            std::cout << "Lifespan: " << M_beingLifespan[i] << "\n";
            std::cout << "Current Age: " << M_beingCurrentAge[i] << "\n";
            std::cout << "Has Mated: " << M_hasMated[i] << "\n";
            std::cout << "Is Offspring: " << M_isOffspring[i] << "\n";
            std::cout << "Is Coupled: " << M_isCoupled[i] << "\n\n";
        }
    
    
    
    
        //Females
        for(int i = 0; i < femaleCurrentPopulation; i++)
        {
            F_beingNames.push_back(i);
            F_beingGenders.push_back("Female");
            F_cleanDna.push_back(100);
            F_defectiveDna.push_back(0);
            F_generation.push_back(1);
            F_relationship.push_back("Self");
            F_parentNames.push_back(std::make_pair(-1, -1));
            F_beingLifespan.push_back(80);
            F_beingCurrentAge.push_back(1);
            F_hasMated.push_back(false);
            F_isOffspring.push_back(false);
            F_isCoupled.push_back(false);
        }
    
    
        for(int i = 0; i < femaleCurrentPopulation; i++)
        {
            std::cout << "Name: " << F_beingNames[i] << "\n";
            std::cout << "Gender: " << F_beingGenders[i] << "\n";
            std::cout << "Clean DNA%: " << F_cleanDna[i] << "\n";
            std::cout << "Defective DNA%: " << F_defectiveDna[i] << "\n";
            std::cout << "Generation: " << F_generation[i] << "\n";
            std::cout << "Relationship: " << F_relationship[i] << "\n";
            std::cout << "Parents: " << M_parentNames[i].first << " " << M_parentNames[i].second << "\n";
            std::cout << "Lifespan: " << F_beingLifespan[i] << "\n";
            std::cout << "Current Age: " << F_beingCurrentAge[i] << "\n";
            std::cout << "Has Mated: " << F_hasMated[i] << "\n";
            std::cout << "Is Offspring: " << F_isOffspring[i] << "\n";
            std::cout << "Is Coupled: " << F_isCoupled[i] << "\n\n";
        }
    
    
        /*TO DO
        //The rest of the program should pair up couples and create offspring, and apply any genetic penalties to them if need be.
        */
    
    
        bool appLoopEnd = false;
    
    
        std::cout << "\n\n";
    
    
        srand(time(NULL));
    
    
        int maleName{};
        int femaleName{};
    
    
        while(!appLoopEnd)
        {
            for(int i = 0; i < 200; i++)
            {
                //Makes sure rand is seeded so we get a random male and female each time.
                maleName = rand() % maleCurrentPopulation;
                femaleName = rand() % femaleCurrentPopulation;
    
    
                //Check to see if there are any males or females that can be paired up. if either pop reaches 0, it will stop.
                if(maleCurrentPopulation > 0 && femaleCurrentPopulation > 0)
                {
                    //Randomly choose pair of beings.
                    pairBeingsUp.push_back(std::make_pair(maleName, femaleName));
    
    
                    
                    if(pairBeingsUp[i].first != maleName && pairBeingsUp[i].second != femaleName)
                    {
                        maleCurrentPopulation--;
                        femaleCurrentPopulation--;
    
    
                        std::cout << pairBeingsUp[i].first << " " << pairBeingsUp[i].second << "\n";
                    }
                }
            }
        }
    
    
    
    
        return 0;
    }
    Last edited by CH1156; 08-29-2018 at 06:34 AM.

  2. #2
    Guest
    Guest
    Regarding the pairing, if each being should only mate with one partner, maybe you can create a list of all beings upfront and remove beings that have been paired (randomly selected)? std::set might be a suitable container for that.

    Some C++ related suggestions:

    Headers inherited from C get a "c" prefix and drop the .h extension:
    Code:
    // C
    #include <stdlib.h>
    #include <time.h>
    
    // C++
    #include <cstdlib>
    #include <ctime>
    Btw, time(nullptr) returns the seconds since Jan 1st 1970, not 2000! And always use nullptr instead of NULL, the latter is C cruft.

    If you find the time (), learn to use the modern chrono header for time related operations.

    If you're writing std:: a lot, consider a local using declaration instead:
    Code:
    void foo()
    {
        using std::vector;
        using std::pair;
    
        vector<int> a;
        vector<double> b;
        vector<pair<int, int>> c;
        vector<pair<char, float>> c;
        //                     ^^
        // btw, you no longer need to add a space here, resolved issue!
    }
    Also note the superior emplace method, where available:
    Code:
    pairBeingsUp.push_back(std::make_pair(maleName, femaleName));
    
    pairBeingsUp.emplace_back(maleName, femaleName); // neat
    In C++, randomization is done using the random header. If you don't have the head for that now, use a little helper class, e.g.:
    Code:
    #include <random>
    
    template<typename T = int>
    class Rnd
    {
    public:
        Rnd(T range_lower, T range_upper)
            : gen(random_device{}())
            , dist(range_lower, range_upper)
        { }
        T get() {
            return dist(gen);
        }
    private:
        mt19937_64 gen;
        uniform_int_distribution<T> dist;
    };
    
    int main()
    {
        Rnd rnd(10, 100); // we want random numbers between 10 and 100
    
        rnd.get(); // returns random number
        rnd.get(); // ...
        rnd.get(); // ...
    }
    I want to get the program working before I split it up into classes and functions
    I doubt that's a good idea. Functions and classes aren't just there for aesthetics, they actually help coding!

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Here's some ideas:
    Code:
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <vector>
    #include <random>
    #include <algorithm>
    
    struct Being {
        int  name;
        char gender;
        int  cleanDna;
        int  defectiveDna;
        int  generation;
        std::string relationship; // son, daughter etc.
        std::pair<int, int> parentNames;
        int  lifespan;
        int  age;
        bool hasMated;
        bool isOffspring;
        bool isCoupled; //Has a mate
    
        Being(int name, char gender)
            : name(name),
              gender(gender),
              cleanDna(100),
              defectiveDna(0),
              generation(1),
              relationship("Self"),
              parentNames(std::make_pair(-1, -1)),
              lifespan(80),
              age(1),
              hasMated(false),
              isOffspring(false),
              isCoupled(false) {}
    
        void print() {
            std::cout << "Name: " << name << '\n';
            std::cout << "Gender: " << gender << '\n';
            std::cout << "Clean DNA%: " << cleanDna << '\n';
            std::cout << "Defective DNA%: " << defectiveDna << '\n';
            std::cout << "Generation: " << generation << '\n';
            std::cout << "Relationship: " << relationship << '\n';
            std::cout << "Parents: " << parentNames.first << ' '
                                     << parentNames.second << '\n';
            std::cout << "Lifespan: " << lifespan << '\n';
            std::cout << "Current Age: " << age << '\n';
            std::cout << "Has Mated: " << hasMated << '\n';
            std::cout << "Is Offspring: " << isOffspring << '\n';
            std::cout << "Is Coupled: " << isCoupled << "\n\n";
        }
    };
     
    int main()
    {
        int maleCurrentPopulation = 4;
        int femaleCurrentPopulation = 4;
        int beingsThatAreDead = 0;
        int matingTime = 5;
        int gestationTime = 30;
        bool isMale = true, isFemale = true, isRelated = false;
        std::vector<std::pair<int, int>> pairs;
        std::vector<Being> males, females; 
     
        //Setup Gen 1 Beings
     
        //Males
        for(int i = 0; i < maleCurrentPopulation; i++)
            males.push_back(Being(i, 'M'));
     
        for(int i = 0; i < maleCurrentPopulation; i++)
            males[i].print();
     
        //Females
        for(int i = 0; i < femaleCurrentPopulation; i++)
            females.push_back(Being(i, 'F'));
     
        for(int i = 0; i < femaleCurrentPopulation; i++)
            females[i].print();
     
        bool appLoopEnd = false;
        int maleName{}, femaleName{};
    
        std::default_random_engine rnd(std::random_device{}());
    
        std::vector<int> m, f;
        for (const auto& b: males)
            m.push_back(b.name);
        for (const auto& b: females)
            f.push_back(b.name);
    
        std::shuffle(m.begin(), m.end(), rnd);
        std::shuffle(f.begin(), f.end(), rnd);
    
        for (int i = 0; i < int(m.size()) && i < int(f.size()); i++)
            pairs.push_back(std::make_pair(m[i], f[i]));
    
        for (int i = 0; i < int(pairs.size()); i++)
            std::cout << pairs[i].first << ' ' << pairs[i].second << '\n';
    }
    If the beings are paired up the same way each run of the program then add #include <chrono> to the includes and change the line that says:
    Code:
        std::default_random_engine rnd(std::random_device{}());
    to
    Code:
        auto seed = std::chrono::high_resolution_clock::
                        now().time_since_epoch().count();
        std::default_random_engine rng(seed);
    A little inaccuracy saves tons of explanation. - H.H. Munro

  4. #4
    Registered User
    Join Date
    Feb 2015
    Posts
    56
    Awesome thank you! I'll play around with this and try to improve on it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. vector initialization random
    By ursu09 in forum C Programming
    Replies: 1
    Last Post: 02-06-2016, 10:04 PM
  2. Random numbers not random?
    By yacek in forum C Programming
    Replies: 6
    Last Post: 10-08-2010, 06:57 PM
  3. random numbers
    By dezz101 in forum C Programming
    Replies: 2
    Last Post: 05-21-2008, 02:04 AM
  4. Random vector
    By elvio.vicosa in forum C Programming
    Replies: 2
    Last Post: 10-16-2007, 02:22 PM
  5. Replies: 4
    Last Post: 11-16-2004, 07:29 AM

Tags for this Thread