4

I want to choose random coordinates on a 8x8 board. The x and y coordinates can only be -8. -6, -4, -2, 0, 2, 4, 6, and 8. I want to choose random coordinates for 20 objects but I don't want any 2 objects to have the same coordinates. Program away in C++!

sudo
  • 329
  • 7
  • 14

5 Answers5

4

You've only got 9 possible values for each coordinate, so that's 81 possible points in all. The simplest solution would be to just enumerate all possible points (eg: in an array or vector), and then randomly select 20.

You can randomly select 20 by picking an index from 0 to 80, swapping that element of the array with index 80, and then randomly picking an index from 0 to 79, swapping that with index 79, and so on 20 times. Then the last 20 elements of your array will be 20 distinct random points.

Laurence Gonsalves
  • 137,896
  • 35
  • 246
  • 299
  • Side note: What you're explaining there is [Reservoir sampling](http://en.wikipedia.org/wiki/Reservoir_sampling) (Just to put a name on it for people who might not know it). And in fact, you can stop the swapping once you have 20 values, as those won't change again. – Joey Nov 13 '10 at 10:59
  • @Joey: "you can stop the swapping once you have 20 values" is why I said "...and so on 20 times". – Laurence Gonsalves Nov 14 '10 at 00:47
1

Take all of the coordinate pairs in your set, and toss them into a list, and generate a random permutation of the list (standard algorithms exist for this, such as the algorithm Laurence is suggesting). Take the first 20 elements of the permutation.

Yuliy
  • 17,381
  • 6
  • 41
  • 47
  • This is a good solution, but it requires memory proportional to the size of the set. I've sometimes wondered if there is a way to solve this problem when the number of possible co-ordinates is astronomical. How might one handle this if there were a trillion coordinate pairs in the set, and we wanted to visit each of them exactly once, but in a random order? – Jeremy Friesner Nov 13 '10 at 07:39
  • As long as you can enumerate your points and efficiently compute the position of an arbitrary point directly from its sequence number, you can use any efficient 1D sampling algorithm, such as Floyd's algorithm - see my answer for some more details. – Fabian Giesen Nov 13 '10 at 09:07
1

If you can enumerate all coordinates on the board, you can use any sampling algorithm. You're on a 9x9 grid; just pick 20 values out of the range [0,80] and then translate them into grid coordinates:

// Say the number picked is "n"
int x = ((n % 9) - 4) * 2;
int y = ((n / 9) - 4) * 2;

You can use any sampling algorithm to generate the ns; check out the answers to this question, for example.

The advantage of this approach over generating the points explicitly is that you can save quite a bit of memory (and processing time) on large grids. If they're really large and you're picking a small simple, the obvious algorithm works fine too: Just pick a random point and try again if you already picked it. The only problem with this algorithm is that it can end up doing quite many retries if you're selecting a large fraction of a set.

Community
  • 1
  • 1
Fabian Giesen
  • 3,231
  • 16
  • 16
0

Putting Laurence's algorithm in program. Its working fine.

#include <iostream>
#include <vector>
#include <ctime>
using namespace std;

//To store x and y coordinate of a point
struct Point
{
    int x, y;
};

int main()
{
    vector<Point> v;
    Point p;
    //Populate vector with 81 combinations.
    for(int i = -8; i < 10; i += 2)
    {
        for(int j = -8; j < 10; j += 2)
        {
            p.x = i;
            p.y = j;
            v.push_back(p);
        }
    }
    srand(time(NULL));

    int lastIndex = 80;
    for(int i = 0; i < 20; i++)
    {
        int randNum = rand() % (81-i);
        //Swap to isolate chosen points.
        std::swap(v[randNum], v[lastIndex-i]); 
    }

    //Print chosen random coordinates
    cout<<"Random points chosen are "<<endl;
    for(int i = 61; i < 81; i++)
    {
        Point p = v[i];
        cout<<p.x<<"\t"<<p.y<<endl;
    }
}
bjskishore123
  • 6,144
  • 9
  • 44
  • 66
0

You could use std::random_shuffle for instance, since you have a finite number of integer coordinates. So just shuffle that set of vectors/positions around. You can also pass your own RNG to random_shuffle as a function object.

Example:

#include <algorithm> //for copy and random_shuffle
#include <utility>   //for pair and make_pair
#include <vector>

...

std::vector<std::pair<int, int> > coords;
std::vector<std::pair<int, int> > coords20(20);
for(int y=-8; y<=8; y+=2)
    for(int x=-8; x<=8; x+=2)
        coords.push_back(std::make_pair(x,y));

std::random_shuffle(coords.begin(), coords.end());    
std::copy(coords.begin(), coords.begin() + 20, coords20.begin());