1

I'm trying to produce do some processing on a random permutation of the alphabet, however each permutation produces the same result despite using srand(myseed)
I have included the <algorithm> header.

string create_permutation(unsigned seed)
{
    srand(seed);
    string permutation = ALPHABET;
    random_shuffle(permutation.begin(), permutation.end());
    return permutation;
}

cout << create_permutation(2) << endl; // or 3, 4, 5 etc
// continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP

Any help would be greatly appreciated.

EDIT: Minimal, Complete, and Verifiable example

EDIT 2: adjustment to mcve

#include <iostream>
#include <algorithm>   

using namespace std;

const string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
string create_permutation(unsigned seed)
{
    srand(seed);
    string permutation = ALPHABET;
    random_shuffle(permutation.begin(), permutation.end());
    return permutation;
}

int main(){    
    cout << create_permutation(2) << endl; // or 3, 4, 5 etc
    // continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP
    return 0;
}
Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Nick Lewers
  • 109
  • 1
  • 10
  • related/dupe: http://stackoverflow.com/questions/1108780/why-do-i-always-get-the-same-sequence-of-random-numbers-with-rand – NathanOliver Apr 19 '16 at 17:19
  • 1
    I did browse the issue before posting, with each post holding any similarity to mine the solution has always been to use _srand(seed)_ which I have already done. – Nick Lewers Apr 19 '16 at 17:22
  • 1
    Related: stop using `random_shuffle` and start using [`std::shuffle`](http://en.cppreference.com/w/cpp/algorithm/random_shuffle). The former is deprecated and will be dropped eventually. See the last sample in the link provided for an example of how to do this. – WhozCraig Apr 19 '16 at 17:23
  • What is your seed and where did you get it from? – Khalil Khalaf Apr 19 '16 at 17:23
  • Added an mvce. Hope that helps. – Nick Lewers Apr 19 '16 at 17:33
  • 4
    You complete example is not very complete. You can't run it. – NathanOliver Apr 19 '16 at 17:33
  • Are you passing the same seed every time? – Jim Mischel Apr 19 '16 at 17:35
  • 2
    If you are using the same seed every time: Go read the docs. Otherwise, [cannot reproduce](http://coliru.stacked-crooked.com/a/0271e625ab0b8c3a). – Baum mit Augen Apr 19 '16 at 17:36
  • @NathanOliver It does not have to be runnable, it needs to be complete yet minimum. Unless there is a reason that this program ***must*** be ran, then what the author has provided is fine. Also, you should always ask the author to provide the needed details and give them time to provide these details. After they fail to do so, then you should flag the question and suggest others to do so as well. – Matt C Apr 19 '16 at 17:40
  • @BaummitAugen I'm so sad to see that even our long time members who have earned so much reputation are so quick to judge a question. 1) If you think this situation is not reproducible, you should first ask the author to provide more details that could possibly reproduce the outcome. 2) Only after giving the author a respectable amount of time to provide a few quick details, should you flag the post as "cannot reproduce". 3) This post is reproducible! You just didn't do the research to see what was need to produce the results. Using his platform and compiler, you will get the same results. – Matt C Apr 19 '16 at 17:50
  • 1
    @MatthewCliatt Hey the Meta Police is here! 1) I already gave him the link to the MCVE help page which tells him to *"Make sure all information necessary to reproduce the problem is included"*. 2) So far, no one has voted to close this, so I don't get your point. 3) *"This post is reproducible!"* Not with the information he provides. *"Using his platform and compiler, you will get the same results."* I cannot do that without knowing which platform that is. – Baum mit Augen Apr 19 '16 at 17:57
  • @MatthewCliatt, if you change the parameters so you don't resuse the same seed, the problem is not reproducible. The primary bug hinges on the reuse of the same seed. – user4581301 Apr 19 '16 at 17:57
  • @NickLewers, change the parameter for `create_permutation` to take in `unsigned int seed` not `unsigned seed`. – Matt C Apr 19 '16 at 17:58
  • @MatthewCliatt That's the exact same thing. – Baum mit Augen Apr 19 '16 at 17:59
  • @BaummitAugen _"I cannot do that without knowing which platform that is."_ Of course not, that is why you should ***ask*** for that information. – Matt C Apr 19 '16 at 18:07
  • @user4581301 The author has in a comment that passing any of the numbers, `2, 3, 4, or 5, etc` will result in the same outcome. The same seed is not always used. – Matt C Apr 19 '16 at 18:08
  • 1
    In that case, back to Baum mit Augen's statement of non reproducible. I can't reproduce either. – user4581301 Apr 19 '16 at 19:03

2 Answers2

7

The problem

  • The shuffles aren't random because shuffle_random is using the same seed for the random number generator each time it is called.

srand does not seed the random_shuffle function, it seeds rand and random_shuffle usually calls rand, but does not have to.

random_shuffle has two forms:

  • One that takes 2 arguments (begin/end iterators)

  • One that takes 3 (begin/end iterator and a random generator).

You have demonstrated that you know how to use the first form, but the problem with the first form is that it is implemented differently on different platforms and with different compilers. It may not use rand() at all, which is the function that srand seeds.

You should use the 3 argument form and provide the random number generator as a parameter to the function.

You can follow this detailed answer to learn how to make your own random number generator, or you can provide rand() to the random_shuffle function as the random number generator.

Community
  • 1
  • 1
Matt C
  • 4,470
  • 5
  • 26
  • 44
0
  1. When you seed the random number generator, you set the starting point for an algorithm that will provide a sequence of psuedorandom numbers. If you always use the same seed, the algorithm will always have the same starting point and always generate the same sequence of numbers.
  2. Every time you call srand, you reset the seed and reset the starting point for the algorithm.
    1. A common bug here is to repeatedly call srand. Unless you have a very good reason not to (and if you do, you probably shouldn't use rand and srand at all. Look to the <random> library) you should call srand once at the beginning of the program to seed the generator once and ever after use that seed.
    2. srand is also quite expensive. From a performance standpoint, you don't want to call it often.

So: since every call to create_permutation calls srand with the seed parameter and create_permutation is always called with the same seed value, for a given implementation of the random number generator, create_permutation will always use the same random number sequence and thus generate the same permutation.

A quick example that will generate different permutations, so long as the program is not run more often than once per second is

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

const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::string create_permutation()
{
    std::string permutation = ALPHABET;
    std::random_shuffle(permutation.begin(), permutation.end());
    return permutation;
}

int main(){
    srand(time(NULL)); // caveat: time's minimum resolution is 1 second.
                       // multiple executions of this program within 1
                       // second will get the same time and use the same seed.
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    return 0;
}

A more modern approach:

#include <random>
#include <algorithm>
#include <iostream>
#include<string>

const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::random_device rd; // Warning: implementation of this is allowed to be stupid and 
                       // return the same value every time. Does not work in mingw 4.8
                       // Can't speak for 4.9 or greater
std::mt19937 randomizer(rd());


std::string create_permutation()
{
    std::string permutation = ALPHABET;
    std::shuffle(permutation.begin(), permutation.end(), randomizer);
    return permutation;
}


int main()
{
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
    std::cout << create_permutation() << std::endl;
}
user4581301
  • 33,082
  • 7
  • 33
  • 54