27

I was reading up on this : http://www.cplusplus.com/reference/algorithm/random_shuffle/ and wondered if its possible to random_shuffle an array of int elements. This is my code

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int a[10]={1,2,3,4,5,6,7,8,9,10};

    cout << a << endl << endl;

    random_shuffle(a[0],a[9]);

    cout<<a;
}

I got this error:

error C2893: Failed to specialize function template
    'iterator_traits<_Iter>::difference_type *std::_Dist_type(_Iter)'.

My question are:

  1. Is it possible to shuffle an int array using random_shuffle. If yes, I would like to learn how to do it.

  2. Is random_shuffle only applicable to templates?

  3. What does my error mean?

jww
  • 97,681
  • 90
  • 411
  • 885
Computernerd
  • 7,378
  • 18
  • 66
  • 95

5 Answers5

55

You need to pass pointers to a[0] and a[10], not the elements themselves:

random_shuffle(&a[0], &a[10]); // end must be 10, not 9

In C++11, you can use std::begin and std::end:

random_shuffle(std::begin(a), std::end(a));
Mankarse
  • 39,818
  • 11
  • 97
  • 141
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
4

Try replacing

random_shuffle(a[0],a[9]);

with

random_shuffle(&a[0], &a[10]);

From: http://www.java2s.com/Code/Cpp/STL-Basics/Userandomshufflealgorithmswitharray.htm

Mankarse
  • 39,818
  • 11
  • 97
  • 141
Theo20185
  • 56
  • 2
3

random_shuffle takes iterators, rather than elements. Try either:

std::random_shuffle(a, a + 10);

or

std::random_shuffle(std::begin(a), std::end(a));

std::random_shuffle can be used on any pair of random access iterators, and will shuffle the elements in the range denoted by those iterators.

The error occurs because ints are not iterators, and so std::random_shuffle is unable to use the given ints as iterators.

Mankarse
  • 39,818
  • 11
  • 97
  • 141
1

Just changing the arr to a pointer does not solve the solution. This will make the array swap to one type of permutation. This means that if you rerun the program, your array will be shuffled into the exact same way as it did in the previous run.

To fix this - the function offers a third parameter which acts as a seed. So the correct implementation of the function is as follows.

1) Have a function or a lamda that generates a random number. This will act as your seed.

int myrandom (int i) { return std::rand()%i;}

Make sure to set the seed of the internal random number generator.

std::srand ( unsigned ( std::time(0) ) );

2) Insert this function as the third arguement in the random_shuffle function call.

std::random_shuffle ( myvector.begin(), myvector.end(), myrandom);

This will result in an always random shuffled array. Make sure to include the following:

#include <algorithm>    // std::random_shuffle
#include <vector>       // std::vector
#include <ctime>        // std::time
#include <cstdlib>      // std::rand, std::srand
0

Worked for me this way:

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
    int a[10]={0,1,2,3,4,5,6,7,8,9};

    for (unsigned i = 0; i < 10; i++)
    {
        cout << a[i];
    }
    cout << endl;

    random_shuffle(&a[0],&a[10]);

    for (unsigned i = 0; i < 10; i++)
    {
        cout << a[i];
    }
    cout << endl;
}
Renato Aloi
  • 300
  • 2
  • 9
  • 1
    For some reason this always shuffles the array in the same order. Or is this what shuffle is about? – AlexPawlak Oct 27 '14 at 16:14
  • 1
    @Koliat see Grant's answer – 2br-2b Mar 06 '20 at 14:34
  • 2
    @2br-2b amazing it took 3 years to get an answer to my comment, and 6 years to be reminded to check the answer to the comment :-) And to be fair, '2014 was about the last time I touched C++ :-) – AlexPawlak Apr 23 '20 at 20:03