Generate 10digits random number without repeating number - page 2

 

Another idea to shuffle an array

string getPassword()
  {
   int val[][2];

   ArrayResize(val, 10);
   for(int i = 0; i < 10; i++)
     {
      val[i][0] = MathRand();
      val[i][1] = i;
     }

   // This will randomize the array
   ArraySort(val);

   string password = "";
   for(int i = 0; i < 10; i++)
      password += IntegerToString(val[i][1]);

   return(password);
  }

void OnStart()
  {
   MathSrand(GetTickCount());

   Print(getPassword());
   Print(getPassword());
   Print(getPassword());
   Print(getPassword());
  }
 
amrali:

Another idea to shuffle an array

I am VERY HAPPY about your 15lines of CODES which is very EXACT of what I need. I give you two thumbs up for sharing this ideas and knowledge. attached file are sample print-out. happy coding.

amrali
amrali
  • 2020.12.26
  • www.mql5.com
Trader's profile
Files:
amrali.jpg  223 kb
 

The Fisher-Yates algorithm is also  a well-know method to shuffle an array:

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

//--- Fisher-Yates algorithm
   for(int i = 9; i > 0; i--)
     {
      int j = MathRand() % 10;
      int temp = val[i];
      val[i] = val[j];
      val[j] = temp;
     }

   string password = "";
   for(int i = 0; i < 10; i++)
      password += IntegerToString(val[i]);

   return(password);
  }

void OnStart()
  {
   MathSrand(GetTickCount());

   Print(getPassword());
   Print(getPassword());
   Print(getPassword());
   Print(getPassword());
  }
 
Very good and interesting info, thank you for providing.

I would like to point out, in terms of randomness, the function MathRand() and especially in terms of the return value. It is important to understand randomness and it's behaviour.

Using modulo on mql implementation of function MathRand () gives biased results.

Only 2 and a power of 2 can be used reliably on the return value of this function.


Edit:

https://www.mql5.com/en/forum/58547

Random number generator within range in mql5
Random number generator within range in mql5
  • 2015.05.10
  • www.mql5.com
Is it possible within MQL5 to generate a random number between a set starting point and ending point...
 
Michael Quinatadcan Macasil Macasil:

I am VERY HAPPY about your 15lines of CODES which is very EXACT of what I need. I give you two thumbs up for sharing this ideas and knowledge. attached file are sample print-out. happy coding.

I suppose you know that such password could be cracked very easily.
 

Hi Dominik

I have tested it before and I can confirm, that modulo bias does not affect the shuffle algorithm much. The unbiasness of the RNG used is not as important as unbiasness of the shuffle algorithm itself.

Here is a nice website to compare several shuffle algorithms using matrix diagrams. https://bost.ocks.org/mike/shuffle/compare.html

 

No matter the randomnes given, as its underlying data input, you will have a significant effect, I would say we all agree, MathRand() is the input to control the behaviour of the "algorithm" (here a for loop). 

Then, no matter what you do, the arising behaviour is given by the input. So here we will use the next higher 0x02 to the power of 0d04 resulting in 0d00 to 0d15 in decimal (Base10). So when using modulo on this input will wrap around at 16. Since we need to wrap 0d10 numbers around to cover 0d16 numbers in "space" you get exactly 4 overlapping, therefore the numbers from 0d00 to 0d05 will significantly more often selected. As you can see, this will lead to the fact, that higher elements in the array, (Here the length of the generated password) will not be selected as often for a candidate as the numbers, or elements in the array, between 0d00 and 0d05.

Concerning the quality of the algorithm. 

 
Dominik Egert:

No matter the randomnes given, as its underlying data input, you will have a significant effect, I would say we all agree, MathRand() is the input to control the behaviour of the "algorithm" (here a for loop). 

Then, no matter what you do, the arising behaviour is given by the input. So here we will use the next higher 0x02 to the power of 0d04 resulting in 0d00 to 0d15 in decimal (Base10). So when using modulo on this input will wrap around at 16. Since we need to wrap 0d10 numbers around to cover 0d16 numbers in "space" you get exactly 4 overlapping, therefore the numbers from 0d00 to 0d05 will significantly more often selected. As you can see, this will lead to the fact, that higher elements in the array, (Here the length of the generated password) will not be selected as often for a candidate as the numbers, or elements in the array, between 0d00 and 0d05.

Concerning the quality of the algorithm. 

The real issue with MathRand() is its limited range, it cannot shuffle arrays > 32768 elements effectively.

You can use my implementation for pcg32 generator to shuffle larger arrays. https://www.mql5.com/en/code/25843

Edit: A really good article on wikipedia https://www.wikiwand.com/en/Fisher%E2%80%93Yates_shuffle

#include <Random.mqh>   //https://www.mql5.com/en/code/25843
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
template<typename T>
void Swap(T &var1, T &var2)
  {
   T temp = var1; var1 = var2; var2 = temp;
  }
//+------------------------------------------------------------------+
//| Shuffle the sort order of array elements in-place.               |
//+------------------------------------------------------------------+
template<typename T>
void ArrayShuffle(T &arr[])
  {
   CRandom pcg;
   int size=ArraySize(arr);
//--- Fisher-Yates algorithm
   for(int i=size-1; i > 0; --i)
      Swap(arr[i], arr[pcg.RandomInteger(i + 1)]);
  }
Class CRandom
Class CRandom
  • www.mql5.com
Random number generation using the 32-bit PCG generator.
 
Thank you for showing nice content.

As the Wikipedia Article points out how random numbers are selected in the algorithm, this is not reflected in the upper function. The here shown code always uses 10.

But independent of this issue, in fact, yes only 2^15 is possible. This is a quite poor granularity.

To remove the bias from the upper code, I suggest doing it following:

(10.0 / MathRand())

As your index calculation.









 

You would use it like: ArrayShuffle( {0,1,2,3,4,5,6,7,8,9} ). BTW, granularity is not a technical term. Period means the range of RNG, and precision of floating-point number. 

Reason: