0

I am trying to store a point into an array. The array has to be a size of 10 and the points have to be a random number from 0 to 100. I am going to be using this array and then organize it through quick sort, and figure out which points are the closest together. Doing some research I found that the Utility class has something that I think will work so I am trying to find out how to make the array generate with random points. One thing is I need the array to be either pass by reference or however way just to make sure I can have this array in main.

#include <iostream>
#include "qsort.h"
#include <stdlib.h>
#include <utility>

using namespace std;

const int ARRAY_SIZE = 10; 

void initializePairs(pair<int,int> array);

int main()
{
    //pair<int, int> shortPointArray[ARRAY_SIZE];
    /*pair<int,int> temp = make_pair(5,6);
    pair<int,int> shortPointArray[1];
    shortPointArray[0] = temp;*/

    pair<int,int> shortPointArray[1];
    //qsort sorting;

    initializePairs(shortPointArray);

    return 1;
}

void initializePairs(pair<int,int> array)
{
    int x;
    int y;
    pair<int,int> temp;

    for(int i = 0; i < ARRAY_SIZE; i++)
    {   
        x = rand() % 100;
        y = rand() % 100;
        temp = make_pair(x,y);
        array[i] = temp;
    }   
}
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 2
    … what is your question? This is a Q&A site, not a "do my homework for me" site. – CBHacking Mar 10 '18 at 03:12
  • 1
    You might consider posting your question to a site that has "forum" somewhere in the name. This site is strict about the guidelines for posting questions. – SaganRitual Mar 10 '18 at 03:13
  • Yeah I am wondering how to randomly populate an array with with points (x,y) being populated randomly. The initializePairs function isn't working @CBHacking – Programmer1010 Mar 10 '18 at 05:29
  • @GreatBigBore Yeah I am asking how to use the Utility library populating an array with (x,y) randomly – Programmer1010 Mar 10 '18 at 05:30
  • @Programmer1010 I understand. That's why I'm steering you away from this site. The guidelines are strict, and people will mistreat you. Have a look [**here**](https://stackoverflow.com/help/on-topic). They mean for you to read them all before you post anything, and comply with them all. Peace and luck to you. – SaganRitual Mar 10 '18 at 05:32
  • All good I figured it out just needed to add a pointer and some other quick things @GreatBigBore – Programmer1010 Mar 10 '18 at 05:50

1 Answers1

0

It isn't all to hard to do what you are looking for:

main.cpp

#include <iostream>
#include <vector>
#include <algorithm>
#include <random>

#include "Point.h"

int main() {
    std::random_device rd; // Random Device: Used To Seed Mersenne Random Generator
    std::mt19937 gen;      // Mersenne Twister
    gen.seed( rd() );      // Seed The Generator
    std::uniform_int_distribution<> dist(0, 100); // Uniform Int Distribution between [a, max]

    // Point<int>
    std::vector<Point<int>> points;
    points.reserve( NUM_POINTS );

    for ( std::size_t i = 0; i < NUM_POINTS; i++ ) {
        // Instead of creating a temporary stack copy each iteration
        // I chose to use the constructor directly and instead of
        // push_back, I'm using emplace_back.
        // Point<int> p( dist( gen ), dist( gen ) );
        // points.push_back( p );

        points.emplace_back( Point<int>( dist( gen ), dist( gen ) ) );
    }

    std::cout << "Showing 10 points of type int with random (x,y):\n";
    for ( auto& p : points ) {
        std::cout << p;
    }
    std::cout << std::endl;

    // Point<float>
    std::vector<Point<float>> points2;
    points.reserve( NUM_POINTS );
    std::uniform_real_distribution<float> dist2( 0, 100.0f );

    for ( std::size_t i = 0; i < NUM_POINTS; i++ ) {
        // Instead of creating a temporary stack copy each iteration
        // I chose to use the constructor directly and instead of
        // push_back, I'm using emplace_back.
        // Point<float> p( dist( gen ), dist( gen ) );
        // points2.push_back( p );

        points2.emplace_back( Point<float>( dist( gen ), dist( gen ) ) );
    }

    std::cout << "Showing 10 points of type float with random (x,y):\n";
    for ( auto& p : points2 ) {
        std::cout << p;
    }
    std::cout << std::endl;

    // Sorting the containers:
    std::sort( points.begin(), points.end() );
    std::sort( points2.begin(), points2.end() );

    std::cout << "Showing the sorted points with type int (x,y):\n";
    for ( auto& p : points ) {
        std::cout << p;
    }
    std::cout << std::endl;

    std::cout << "Showing the sorted points with type float (x,y):\n";
    for ( auto& p : points2 ) {
        std::cout << p;
    }
    std::cout << std::endl;


    std::cout << std::endl;
    system( "PAUSE" );
    return 0;
}

Point.h

#ifndef POINT_H
#define POINT_H

#include <iostream>
#include <tuple>     // std::tie

const std::size_t NUM_POINTS { 10 };

// Need class Point prototype for operator<< declaration
template<class> class Point;     

// Need operator<< declaration for class template Point's friend declaration 
template<class T>
std::ostream&  operator<<( std::ostream& out, const Point<T>& );

// Class Declaration & Definition
template<class T>
class Point {
public:
    T _x;
    T _y;
    Point() : _x( 0 ), _( 0 ) {}
    Point( T x, T y ) : _x( x ), _y( y ) {}
    Point( T& x, T& y ) : _x( x ), _y( y ) {}
    Point( T* x, T* y ) : _x( *x ), _y( *y ) {}

    // friend prototype: notice the extra <> in this declaration
    // It tells the compiler that this friend function will be a specialization of this class template
    friend std::ostream& operator<< <>( std::ostream& out, const Point<T>& p );

    // operator< for comparison
    bool operator<( Point<T>& p ) {
        // std::tie makes it real easy to compare a (set) of values.
        return std::tie( _x, _y ) < std::tie( p._x, p._y );
    }

    // operator> for comparison
    bool operator<( Point<T>& p ) {
           return !(*this < p );
    }

    // operator== for comparison
    bool operator==( Point<T>& p ) {
        return (this->_x == p._x && this->y == p._y );
    }                
};

// operator<< definition
template<class T>
std::ostream& operator<<( std::ostream& out, const Point<T>& p ) {
    return out << "(" << p._x << "," << p._y << ")\n";
}

#endif // !POINT_H

As for the implementation of the class template Point<T> you can refer to the comments in the header file.


For the details of the main function I will go over some of those details.

For generating your random values I would high suggest staying away from random() or any of its related deprecated or soon to be functions. I would begin by learning and using Pseudo Random Generators that can be found in the standard library along with different types of distributions: these can all be found in <random> header file. You can use std::default_random_engine() but I prefer to use std::random_device We can use that to SEED the engine(generator) of our choosing. One of the more popularly used engines or generators is known as the Mersenne Twister which is std::mt19937 and there is a 65bit version of it too. It is quite simple to do.

{ 
    std::random_device rd; // create an instance of our device to seed with
    std::mt19937 gen;      // create an instance of our generator (engine)
    gen.seed( rd() ); // This seeds the generator (engine)
    // Now we need a distribution along with its data type
    // there are different versions of these distributions for different types
    // Some are for integral types while others are for floating point types

    // Here we want a uniform distribution for int so we default the template
    std::uniform_int_distribution<> dist(0, 100); //random from [0,100]
    // otherwise we could of done
    std::uniform_int_distribution<unsigned int> dist2( 0, 50 ); // random from [0, 50]

    // There are other types of distributions
    std::normal_distribution<> a;
    std::poisson_distribution<> b;
    // etc.

    // If the distributions say "real" they are floating point types
    std::uniform_real_distribution<float> f;
    std::uniform_real_distribution<double> d;

    // Just as there are different distributions there also other
    // generators or engines beside the mersenne twister.

    // There is another way besides using `random_device` to seed the generator
    // you can use <chrono> header to use `std::chrono::high_resolution_clock
    // to seed the generator
    // You can also seed by const value 
    // and you can use std::seed_seq;
}

You can find all the information that you need for doing Pseudo Random Generators & Distributions from this web page.


So now that we have our random generators up and working the next step is we declare a std::vector<Point<int>> then we use its reserve function and set it with our const NUM_POINTS. Then we go through a for loop for NUM_POINTS iterations and we populate our container with a random (x,y) set of values. Then we display the results using a ranged base for loop.

I repeat the above process to show it being done with floats. I did it this way to show the usefulness of templates.

After that I finally sort the containers simply by calling std::sort( begin, end ) using the vector's iterators. Then I go back and use a ranged base for loop to show both of the sorted vectors.

using std::sort works very easy since we defined an overloaded operator<() for our class and we used std::tie to easily compare them. This shows you the power of being of the standard library by bringing together a bunch of parts like set of Legos!

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59