14

Is there some function, similar to srand(), that I need to call to make sure that std::random_shuffle() always produces different results? i.e. if I call it several times with the same data, I want the order to be different every time. How can I make sure of that?

laurent
  • 88,262
  • 77
  • 290
  • 428

6 Answers6

14

std::random_shuffle has two forms. One that takes 2 arguments (begin/end iterators), and one that takes 3 (begin/end iterator and a random generator).

The first form uses std::rand(), so you would use std::srand() to seed it's random number generator. You can also use the 3-argument version and provide the RNG yourself.

Dave S
  • 20,507
  • 3
  • 48
  • 68
  • 7
    As I understand it, how the first form implements it is its business. Some platforms may not use `std::rand`. – Tom Kerr Aug 03 '11 at 19:26
  • You're right. I was looking at the libstdc++ version. The original author should consult the documentation for your STL. Or if they don't want to rely on that, they should use the 3rd form and use something like `boost::random` or the C++0x `std::random`. – Dave S Aug 03 '11 at 19:30
6

std::random_shuffle has a template overload for specifying the RNG.

template <class RandomAccessIterator, class RandomNumberGenerator>
  void random_shuffle ( RandomAccessIterator first, RandomAccessIterator last,
                        RandomNumberGenerator& rand );

reference

Tom Kerr
  • 10,444
  • 2
  • 30
  • 46
5

random_shuffle is deprecated since C++14 (removed in C++17) and replaced with shuffle (exists since C++11) http://en.cppreference.com/w/cpp/algorithm/random_shuffle

possible usage:

shuffle(items.begin(), items.end(), std::default_random_engine(std::random_device()()));
sluki
  • 524
  • 5
  • 15
3

I think you can give a random generator functor to std::random_shuffle, so you can be able to fully control the random number generation. Looking here, this functor takes the place of the RandomNumberGenerator template argument.

onkar
  • 4,427
  • 10
  • 52
  • 89
neodelphi
  • 2,706
  • 1
  • 15
  • 22
3

Generally call srand(time(NULL)) before calling std::random_shuffle() would give you what you need, it give you different result each time you call std::random_shuffle(). It's because std::random_shuffle() internally calls rand() in many popular implementations (e.g. VS-2008 and GCC).

Of course you can supple a RNG yourself if you want to call the other overloaded std::random_shuffle with a extra parameter.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
RoundPi
  • 5,819
  • 7
  • 49
  • 75
2

As a last resort, you can:

  • Call std::random_shuffle
  • Compute a hash of the sequence, store it in a std::set
  • Discard if the hash is already present

I fail to see how using a custom generator could guarantee that the sequence is unique.

Alexandre C.
  • 55,948
  • 11
  • 128
  • 197