Given a 7x4 array generate four random numbers from the array with no repetition.

I can already generate four random numbers the problem is the repetition part.

Here's my code so far

int f[4];
int s[4];

for( i = 0; i < 4; i++)
{
  // use as index for array a
  f[i] = rand() % 7;
  s[i] = rand() % 4;

  cout << a[f[i]][s[i]] << "\n";

}

Any suggestions?

Instead of just outputting the values save them to a container. Then each new value you select from the original list can be checked against your new list for uniqueness. Something like:

std::set< int > unique; 

while (unique.size () < 4) {
   f[i] = rand() % 7;
   s[i] = rand() % 4;
   unique.insert(a[f[i]][s[i]]); // duplicates ignored
}

I still get duplicate values

    set< int > unique; 

    for( i = 0; i < 4; i++)
    {
      f[i] = rand() % 7;
      s[i] = rand() % 4;

      unique.insert(a[f[i]][s[i]]);

      cout << a[f[i]][s[i]] << "\n";

    }

Given a 7x4 array generate four random numbers from the array with no repetition.

Your code and your description don't match at all. Where is your 7x4 array?
How do you "generate four random numbers from the array"? what's in the array?

I still get duplicate values

Thats because you are still printing everything (regardless if it makes it in the set). Change your loop condition and only print all the values once you've exited your loop.

How do you "generate four random numbers from the array"?
refer to first post

what's in the array?
random numbers

Change your loop condition and only print all the values once you've exited your loop.
Why will I change the loop condition since I need it to generate the random numbers. How will I print the values once. I tried this.

cout << unique << " "; and cout << a[f[unique]][s[unique]] but they were wrong.

What you are posting is getting farther and farther from real code. Perhaps it is time you posted a full working sample of what you have.

How do you "generate four random numbers from the array"?
refer to first post

Telling me to re-read the post I quoted does NOT answer the question. I'm asking because your first post says this and I don't understand it.

what's in the array?
random numbers

So it's just crap in the array from uninitialize data and you have no idea what the values are. Got it.

What about the 7x4 array?

How do you "generate four random numbers from the array"?
refer to first post

My first post tells you how I generate four random numbers I gave the code.

I can already generate four random numbers the problem is the repetition part.
Here's my code so far

int f[4];
int s[4];

for( i = 0; i < 4; i++)
{
 // use as index for array a
 f[i] = rand() % 7;
 s[i] = rand() % 4;
 cout << a[f[i]][s[i]] << "\n";
}

Regarding the values of the array[7][4] I initialize it with random numbers.

what's in the array?
random numbers

int array[7][4] = { {20, 30, 40, 27},
                    {19, 8, 10, 17},
                    {2, 9, 1, 15},
                    {4, 8, 12, 16},
                    {5, 10, 15},
                    {6, 12},
                    {3}};

Ok i already got how to print the values. If I use the code below it prints four random numbers no duplicates.

set< int > unique; 
set< int >::iterator it;

// first version of printing
while( unique.size() < 4 )
{
  f[unique.size()] = rand() % 7;
  s[unique.size()] = rand() % 4;

  unique.insert(a[f[unique.size()]][s[unique.size()]]);
}

for( it = unique.begin(); it != unique.end(); ++it )
   cout << " " << *it;

But when I switch the code to a for loop. It doesn't give me four random numbers sometimes it gives me two or three sometimes 4. But it does give me unique values.

for( i = 0; i < 4; i++)
{
  f[i] = rand() % 7;
  s[i] = rand() % 4;

  unique.insert(a[f[i]][s[i]]);
}

for( it = unique.begin(); it != unique.end(); ++it )
  cout << " " << *it;

What's the difference between the two version?

And also most of the time the four numbers starts with a 0 even there's no 0 value in the array.

There is a problem with the logic you use to generate the random indexes.

Let's start with something simpler. Suppose you want to get three unique random values from a unidimensional array of four elements. The easiest way to do this is by using random_shuffle:

#include <iostream>
#include <string>
#include <algorithm>
#include <ctime>

using namespace std;

int main()
{
    srand(time(0));

    string value_array[4] = { "one", "two", "three", "four" };

    int index_array[4] = { 0, 1, 2, 3 };

    random_shuffle(index_array, index_array + 4);

    for (int i = 0; i < 3; ++ i)
        cout << value_array[index_array[i]] << endl;
}

Now, there are two ways to scale this in order to accommodate for bidimensional arrays. One of them is wrong (and is very similar to what you're doing) and the other is right. Let's see the wrong way first:

#include <iostream>
#include <string>
#include <algorithm>
#include <ctime>

using namespace std;

int main()
{
    srand(time(0));

    string value_array[3][4] = {
        { "one-a", "two-a", "three-a", "four-a" },
        { "one-b", "two-b", "three-b", "four-b" },
        { "one-c", "two-c", "three-c", "four-c" }
    };

    int index_array_a[3] = { 0, 1, 2 };
    int index_array_b[4] = { 0, 1, 2, 3 };

    random_shuffle(index_array_a, index_array_a + 3);
    random_shuffle(index_array_b, index_array_b + 4);

    for (int i = 0; i < 3; ++ i)
        cout << value_array[index_array_a[i]][index_array_b[i]] << endl;
}

One problem with this is that it just doesn't work if the number of your picks is bigger than the smallest dimension.

But the real problem is that you can never get an output of, let's say ...

one-a
one-b
one-c

... or an output of ...

one-a
one-b
two-b

The right way of doing it is this:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <ctime>

using namespace std;

int main()
{
    srand(time(0));

    string value_array[3][4] = {
        { "one-a", "two-a", "three-a", "four-a" },
        { "one-b", "two-b", "three-b", "four-b" },
        { "one-c", "two-c", "three-c", "four-c" }
    };

    vector<pair<int, int> > index_pairs;

    for (int i = 0; i < 3; ++ i)
        for (int j = 0; j < 4; ++ j)
            index_pairs.push_back(make_pair(i, j));

    random_shuffle(index_pairs.begin(), index_pairs.end());

    for (int i = 0; i < 3; ++ i)
        cout << value_array[index_pairs[i].first][index_pairs[i].second] << endl;
}

But when I switch the code to a for loop. It doesn't give me four random numbers

If you've got a solution that works why would you be interested in one that does not? You post that you have a solution that does what you need but when you change it to something else it fails to work as you intend. What is the motivation to change a working solution?

Sorry, I was wrong. Looking more closely, your code doesn't have the problem I thought it had. This problem only arises when you use random_shuffle carelessly (as I deliberately did in my second example). So, your code that uses std::set is fine.

To make amends for my mistake, let me answer some of your questions.

And also most of the time the four numbers starts with a 0 even there's no 0 value in the array.

There are several zero values in your array :) Check this out:

#include <iostream>

using namespace std;

int main()
{
    int array[3][3] = {
        { 1, 2, 3 },
        { 4, 5 },
        { 6 }
    };

    for (int i = 0; i < 3; ++ i)
    {
        for (int j = 0; j < 3; ++ j)
            cout << array[i][j];

        cout << endl;
    }
}

What's the difference between the two version?

The difference is that the while loop runs as many times as needed to fill the set with four (different) numbers, while the for loop always runs four times. After these four runs, the set may have four (different) values, but it may also have only three or two or even one. Take a look at std::set and how it works.

Also, I want to add here that your code relies on value uniqueness, while the examples I posted rely on index uniqueness. This difference is irrelevant to the method used to get the random sequence (rand-set / random_shuffle). Value uniquness guarantees, well, unique values, even if there are duplicate values in your array. Index uniqueness on the other hand, requires that your array doesn't have duplicate values in order to work properly. But it's useful when what you store in your array is not something trivial.

Edited 4 Years Ago by m4ster_r0shi

If you've got a solution that works why would you be interested in one that does not? You post that you have a solution that does what you need but when you change it to something else it fails to work as you intend. What is the motivation to change a working solution?

I was just wondering what would happen. If the for loop will give me the same results as the while loop. I asked you since maybe you would know :)

To make amends for my mistake, let me answer some of your questions.

It's ok thanks for your suggestion/s anyway.

I already figured out a way to my problem. I converted the 7x4 array into 1 dimensional and use std::set.

This question has already been answered. Start a new discussion instead.