Raised This Month: $ Target: $400
 0% 

Random numbers without repeating


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
KiLLeR.
Senior Member
Join Date: Jul 2014
Location: Bulgaria
Old 05-02-2016 , 11:32   Random numbers without repeating
Reply With Quote #1

PHP Code:
for(new i=0i<5i++)
{
    
num[i] = random_num(110);

So, how to retrieve 4 random numbers between 1 and 10, but without repeating.

I can use something like:
PHP Code:
if((num[0] == (num[1] | num[2] | num[3] | num[4] | num[5])) || (num[1]  == (....)))
{
    
// retrieve a new random number

But I think, that this isn't the most efficient way (even if it works).

Last edited by KiLLeR.; 05-02-2016 at 12:10.
KiLLeR. is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 05-02-2016 , 12:20   Re: Random numbers without repeating
Reply With Quote #2

Don't worry too much about efficiency here.
I ran this code 1 000 000 times with the result of 1.795s. (That's an average of .001795milliseconds per time you randomize 5 numbers... trivial.)

Code:
    for ( new i ; i < sizeof num ; i++ ) {         do num[i] = random_num(1, 10);         while ( AlreadyExists(num[i], num, i) )     } // ... AlreadyExists(num, array[], size) {     for ( new i ; i < size ; i++ )         if ( array[i] == num )             return 1;     return 0; }
__________________

Last edited by Black Rose; 05-02-2016 at 12:25.
Black Rose is offline
siriusmd99
Veteran Member
Join Date: Oct 2013
Location: Republic of Moldova
Old 05-02-2016 , 12:27   Re: Random numbers without repeating
Reply With Quote #3

PHP Code:
for(new i=0i<5i++)
{
   
num[i] = random_num(110);
   while(
num_exists(num[i], num) )
   
num[i] = random_num(110);

}  

bool:num_exists(numbercountsource[]){

 for(new 
jcountj++)
 if(
source[j]==number)
 return 
true;
 
 return 
false;


Last edited by siriusmd99; 05-02-2016 at 12:29.
siriusmd99 is offline
KiLLeR.
Senior Member
Join Date: Jul 2014
Location: Bulgaria
Old 05-02-2016 , 13:54   Re: Random numbers without repeating
Reply With Quote #4

Thanks you! I already made something that seems is working, but I will use your method, because looks better.

PHP Code:
new num[11], temprnum;
            
    for(new 
i=1i<sizeof(num); i++)
    {
        
num[i] = i;
    }
    
    for(new 
i=1i<sizeof(num); i++)
    {
        
temp num[i];
        
rnum random_num(110);
        
        
num[i] = num[rnum];
        
num[rnum] = temp;
    }
    
    new 
randomnum[5];
    
    for(new 
i=0i<5i++)
    {
        
randomnum[i] = num[i+1];
    }
    
    
server_print("%i %i %i %i %i"randomnum[0], randomnum[1],randomnum[2],randomnum[3],randomnum[4]); 

Last edited by KiLLeR.; 05-02-2016 at 13:55.
KiLLeR. is offline
siriusmd99
Veteran Member
Join Date: Oct 2013
Location: Republic of Moldova
Old 05-02-2016 , 14:32   Re: Random numbers without repeating
Reply With Quote #5

Quote:
Originally Posted by Black Rose View Post
Don't worry too much about efficiency here.
I ran this code 1 000 000 times with the result of 1.795s. (That's an average of .001795milliseconds per time you randomize 5 numbers... trivial.)

Code:
    for ( new i ; i < sizeof num ; i++ ) {         do num[i] = random_num(1, 10);         while ( AlreadyExists(num[i], num, i) )     } // ... AlreadyExists(num, array[], size) {     for ( new i ; i < size ; i++ )         if ( array[i] == num )             return 1;     return 0; }
Loooool, we have the same thoughts...., gj..


Also @KiLLeR., you can avoid this thing:

Quote:
server_print("%i %i %i %i %i", randomnum[0], randomnum[1],randomnum[2],randomnum[3],randomnum[4]);
by using this :

PHP Code:
new tmpmsg[16]

for(new 
i5i++)
  
add(tmpmsg15,"%i "randomnum[i])

server_print(tmpmsg); 

Last edited by siriusmd99; 05-02-2016 at 14:33.
siriusmd99 is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 05-02-2016 , 14:33   Re: Random numbers without repeating
Reply With Quote #6

It depends on implementation.
If it actually is 5 values between 1 and 10 it doesn't matter.
But your method of scrambling an array will be more consistent as the previous 2 versions of pure randomizing values will be dependent on the availability of the numbers. As you fill the array and the available numbers become rare, time increases because of retries.

Here's a small example comparing the two functions.
Code:
#include <amxmodx> #include <rose> #define SIZE 5 #define MIN 1 #define MAX 10 #define RANDOMIZER 10 public plugin_init() {     register_plugin("Test Plugin 5", "", "[ --{-@ ]");     server_print("MIN: %d, MAX: %d, SIZE: %d, RANDOMIZER: %d", MIN, MAX, SIZE, RANDOMIZER);         new hTimer = TimerStart();     for ( new l ; l < 1000000 ; l++ )         Randomize_1()     TimerStop(hTimer);     new output[32];     TimerFormat(hTimer, output, charsmax(output), 2)     server_print("Method one, 1 000 000 runs, time: %s", output);     hTimer = TimerStart();     for ( new l ; l < 1000000 ; l++ )         Randomize_2()     TimerStop(hTimer);     TimerFormat(hTimer, output, charsmax(output), 2)     server_print("Method two, 1 000 000 runs, time: %s", output); } Randomize_1() {     static num[SIZE];     for ( new i ; i < sizeof num ; i++ ) {         do num[i] = random_num(MIN, MAX);         while ( AlreadyExists(num[i], num, i) )     } } AlreadyExists(num, array[], size) {     for ( new i ; i < size ; i++ )         if ( array[i] == num )             return 1;     return 0; } Randomize_2() {     static num[SIZE];     static values[MAX];     new temp, r;     for ( new i ; i < sizeof values ; i++ )         values[i] = i + 1;     for ( new i ; i < RANDOMIZER ; i++ ) {         r = random(sizeof values);         temp = values[i % sizeof values];         values[i % sizeof values] = values[r];         values[r] = temp;     }     for ( new i ; i < sizeof num ; i++ )         num[i] = values[i]; }

Here are some examples I ran:
Code:
MIN 1, MAX 10, SIZE 5, RANDOMIZER 10:
Method one, 1 000 000 runs, time: 1s 853ms
Method two, 1 000 000 runs, time: 2s 681ms
Code:
MIN: 1, MAX: 10, SIZE: 5, RANDOMIZER: 30
Method one, 1 000 000 runs, time: 1s 882ms
Method two, 1 000 000 runs, time: 5s 930ms
Code:
MIN: 1, MAX: 5, SIZE: 5, RANDOMIZER: 10
Method one, 1 000 000 runs, time: 2s 960ms
Method two, 1 000 000 runs, time: 2s 428ms
Code:
MIN: 1, MAX: 20, SIZE: 15, RANDOMIZER: 10
Method one, 1 000 000 runs, time: 12s 618ms
Method two, 1 000 000 runs, time: 3s 685ms
Code:
MIN: 1, MAX: 20, SIZE: 20, RANDOMIZER: 50
Method one, 1 000 000 runs, time: 41s 402ms
Method two, 1 000 000 runs, time: 10s 470ms
As you can see, as the size increases and the possible values become more similar to the number of slots to fill the first method gets really slow.
Again, this is 1 000 000 runs. So even 41s equals to an average of .041 milliseconds per run. Again, trivial.
__________________

Last edited by Black Rose; 05-02-2016 at 15:10.
Black Rose is offline
Bugsy
AMX Mod X Moderator
Join Date: Feb 2005
Location: NJ, USA
Old 05-08-2016 , 13:55   Re: Random numbers without repeating
Reply With Quote #7

I know this is already answered but I was bored and put this together.

You must first call PrepRandom() for any min/max combo prior to calling GetRandom() for that min/max combo. Once you call PrepRandom(), you can repeatedly call GetRandom() and you will always get a unique random until all numbers have been used. Once all are used, you will then begin getting the numbers again, and they will be unique until you again use up all the numbers.

Like this. But you cannot cannot call GetRandom on a particular min/max until you first call PrepRandom for that min/max set.
PHP Code:
PrepRandom10 );
GetRandom10 );
GetRandom10 );
GetRandom10 );
GetRandom10 );

PrepRandom500 );
GetRandom500 );
GetRandom500 );
GetRandom500 );
GetRandom500 ); 
PHP Code:

#include <amxmodx>

new const Version[] = "0.1";

//Set this to the absolute max random number that you will attempt to generate.
const MaxRandom 20;

new 
AllNumbers[ ( MaxRandom >> ) + ];

public 
plugin_init()
{
    
register_plugin"Random Number No Dupes" Version "bugsy" );
    
    
PrepRandom20 );
    
    for ( new 
<= 100 i++ )
        
server_print"[%d] Random=%d" GetRandom20 ) );
}

PrepRandomiRanMin iRanMax )
{
    for ( new 
iRanMin <= iRanMax i++ )
        
AllNumbers>> ] |= ( << );
}

public 
GetRandomiRanMin iRanMax )
{    
    static 
UsedNumbers[ ( MaxRandom >> ) + ];
    new 
iRandom bool:bAllUsed=true;
    
    if ( 
iRanMax MaxRandom )
        
set_fail_state"Must increase MaxRandom value: %d > %d" iRanMax MaxRandom );
    
    
//Check if all numbers have already bee nused, if so this will reset the 'used' variable.
    
for ( new sizeofUsedNumbers ) ; i++ )
    {
        if ( 
AllNumbers] && ( AllNumbers] != UsedNumbers] ) )
        {
            
bAllUsed false;
            break;
        }
    }

    
//If all random numbers have already been used, reset variable so they can be re-used.
    
if ( bAllUsed )
        
arraysetUsedNumbers sizeofUsedNumbers ) );
    
    
//Find random number
    
do
    {
        
iRandom random_numiRanMin iRanMax );
    }
    while ( ( 
UsedNumbersiRandom >> ] & ( << iRandom ) ) )  
    
    
//Set current random number as used
    
UsedNumbersiRandom >> ] |= ( << iRandom );
    
    
//Return random number
    
return iRandom;

__________________

Last edited by Bugsy; 05-08-2016 at 14:08.
Bugsy is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:43.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode