0

I am frustrated because I do not know if what I am attempting is even possible.

Lets say I have a list of unsigned numbers. I want to create a seed for a certain pseudorandom number generator algorithm that can generate that specific set of numbers.

When creating the seed, I know the length of the list, and the minimum/maximum numbers.

Here is my current algorithm for generating numbers (C++):

unsigned short rng(unsigned short lowerBounds, unsigned short upperBounds){
    static unsigned short lim = (upperBounds - lowerBounds)+1;
    static unsigned short a = 1; //SEED
    a = a*2 % 32749;
    return (a % lim)+lowerBounds;
}

So for example, I would have the numbers { 63, 37, 82, 34, 75}

I would need to have a seed that would generate those numbers in the first 5 runs (order doesnt matter i suppose)

In simpler terms, I want to control the numbers that an RNG generates

  • How big is the set of numbers you want to generate from? – DavidO Feb 12 '14 at 09:20
  • 1
    `std::shuffle` may help. – Jarod42 Feb 12 '14 at 09:23
  • the set of numbers should be less than a long long (8 bytes) –  Feb 12 '14 at 09:24
  • Could you please provide more precisely the rules of you problem? You have a set of numbers e.g 63, 37, 82, 34, 75, then you have to create generator, that could produce that ser when using specific seed? Or you even don't know the set and you need find generator that (with specific seed) can produce any possible set? – Arsenii Fomin Feb 12 '14 at 09:25
  • Well my initial thought was to put the numbers you want in an array, and randomly select an index, which is why I asked how big the set of numbers is. Since it's *that* large (a range covered by a long long), you're going to have to do it mathematically instead. – DavidO Feb 12 '14 at 09:26
  • @DavidO I removed my comment when I've seen was large... :D Anyway... I suggested to use a table... and pick randomically the index. – Jekyll Feb 12 '14 at 09:26
  • Fomin, I have a set of numbers of length n. I want to create a seed that when used with an RNG algorithm, will recreate that set of numbers –  Feb 12 '14 at 09:28
  • @user3300842 then table the numbers and use a regular uniform distribution to generate an index from 0..(n-1), where n is the slots in the set. If you're looking to create a linear congruential generator for a predefined set of numbers, I can all-but-guarantee you're in a land that you can't even begin to imagine. – WhozCraig Feb 12 '14 at 09:31
  • I am going to read about shuffle, and uniform_int_distribution, but does everyone understand my problem? –  Feb 12 '14 at 09:32
  • Purrformance, that is exactly right! A seed will always generate the exact same output. But instead of starting from the seed, how can i start from the set of numbers? –  Feb 12 '14 at 09:33
  • 1
    If it is as you say, you needn't a seed at all. an rng implementation that overrides `operator()` to *not* do anything except return the next number in a table of numbers would do what you want (and frankly, be somewhat pointless except for testing things like prime-generators for RSA key generation validation and such). The clarity of this question is foggy at best, near-indecipherable at worst. Rather than describing what you think you need, try describing what the root *problem* is you're trying to *solve*. – WhozCraig Feb 12 '14 at 09:36
  • So, how big is `n`, again? – jrok Feb 12 '14 at 09:41
  • I was thinking of a new method of encrypting messages sent between a client and a server. the client would calculate a seed based on what the user's message is, and then send it off to the server. The server would then decode the message by using the seed given by the client. The server would then use the same algorithm that was used to secure the seed, by generating a certain set of numbers. those numbers were to be translated into ASCII –  Feb 12 '14 at 09:43
  • jrok, n could be up to 8 bytes long –  Feb 12 '14 at 09:46
  • Encrypting messages isn't a problem. Get the same symmetric key on both sides and its a done deal. The real difficulty is securing the *key exchange*. Is that the problem you're trying to solve ? Or is this just an exercise in message obfuscation techniques? Regardless, repeating a predefined set of numbers somewhat defeats the point of a seeded rng. The rng algorithm decides the numbers, so long as both sides use the same algorithm and the same seed, you'll get the same numbers. – WhozCraig Feb 12 '14 at 09:51
  • Ah Ok, I understand what you are saying. –  Feb 12 '14 at 09:53
  • But is there no way to create a static RNG seed that is created from a message? –  Feb 12 '14 at 09:54
  • So given a generator, and the first generated values, you want to retrieve a seed (may be not unique) which generates those first values, right ? – Jarod42 Feb 12 '14 at 10:25
  • Given a generator, and a set of values, calculate the seed that when put into the generator, will produce the original set of values –  Feb 12 '14 at 10:26
  • @user3300842: I suggest you to (re)ask as follow: *Title: How can I retrieve seed given a generator and first generated values ? Given this generator: `generator code` Given `lowerBounds` and `upperBounds`. Given `{ 63, 37, 82, 34, 75}` the first generated values. How do I retrieve the initial seed ?* – Jarod42 Feb 12 '14 at 10:45

2 Answers2

1

You could use std::shuffle() if your compiler supports C++11. See the following example:

#include <algorithm>    // std::move_backward
#include <array>        // std::array
#include <random>       // std::default_random_engine
#include <chrono>       // std::chrono::system_clock

int main () {
  // generate your own std::vector or std::array with your own data here
  std::array<int,5> foo {63, 37, 82, 34, 75};

  // obtain a time-based seed:
  unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();

  shuffle (foo.begin(), foo.end(), std::default_random_engine(seed));

  for (int& i: foo) {
    // put your function here
    your_function(i);
  }

  return 0;
}

If your compiler doesn't support C++11 features, you could use std::random_shuffle. See the following example:

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

// random generator function:
int myrandom (int i) { return std::rand()%i;}

int main () {
  std::srand ( unsigned ( std::time(0) ) );
  std::vector<std::size_t> myvector;

  // set your values in myvector somehow :)
  myvector.push_back(63);
  myvector.push_back(37);
  myvector.push_back(82);
  myvector.push_back(34);
  myvector.push_back(75);

  // using built-in random generator:
  std::random_shuffle ( myvector.begin(), myvector.end() );

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

  for (std::vector<std::size_t>::iterator it=myvector.begin(); it!=myvector.end(); ++it) {
    // put your function here
    your_function(*it);
  }

  return 0;
}
101010
  • 41,839
  • 11
  • 94
  • 168
  • 1
    I was referring to std::shuffle() which is available only in C++11, but thanks for the reminder it gave an idea of how you could make it in C++ prior C++11. :) – 101010 Feb 12 '14 at 09:57
  • If i am not mistaken, this code just shuffles the order of the set of numbers. I am looking for the RNG seed to recreate that list of numbers without knowing any other info –  Feb 12 '14 at 10:00
  • What if you store the seed in order to regenerate you pseudo-random sequence. The "seed" in the first example and unsigned ( std::time(0) in the second example. – 101010 Feb 12 '14 at 10:17
  • that would work if i wanted a random sequence. In this case, I start with a static sequence, and I want to create a seed from it that will regenerate it if put back into the algorithm –  Feb 12 '14 at 10:24
1

code first

#include <random>
#include <iostream>

int f(int low, int high)
{
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(low, high);

    return dis(gen);
}

std::uniform_int_distribution will give you a random number in your range this way. If your seed is known as well as the length, here is what you do

std::vector<int> f(int low, int high, unsigned seed, int len)
{
    std::vector<int> ret; // RVO applies, no worries
    std::mt19937 gen(seed);
    std::uniform_int_distribution<> dis(low, high);

    for (int i(0); i<len; ++i) {
        ret.push_back(dis(gen));
    }
    return ret;
}
Nikos Athanasiou
  • 29,616
  • 15
  • 87
  • 153