1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

Returning multiple unique random numbers

Discussion in 'PHP' started by jarvi, Feb 4, 2005.

  1. #1
    I'd like to generate a few random numbers but I don't want them to be the same. For example, the range of numbers is between 1 and 10 and I would like to return 4 unique numbers. Is there a way to do this with a variation of the rand function? Or can anyone suggest an alternative?

    Thanks in advance,
     
    jarvi, Feb 4, 2005 IP
  2. digitalpoint

    digitalpoint Overlord of no one Staff

    Messages:
    38,333
    Likes Received:
    2,613
    Best Answers:
    462
    Trophy Points:
    710
    Digital Goods:
    29
    #2
    Just call the mt_rand() function 4 times.
     
    digitalpoint, Feb 4, 2005 IP
  3. jarvi

    jarvi Well-Known Member

    Messages:
    127
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    103
    #3
    Thanks Shawn however, not quite what I was after. To explain it better:

    <?
    
      $var1 = mt_rand(1,10);
      $var2 = mt_rand(1,10);
      $var3 = mt_rand(1,10);
      $var4 = mt_rand(1,10);
    
      echo $var1 . "<br>";
      echo $var2 . "<br>";
      echo $var3 . "<br>";
      echo $var4 . "<br>";
    
    ?>
    Code (markup):
    The results came out such as 1,5,4,6 or 4,6,4,3 or 8,8,5,6. Now what I would like is for the result set not to include duplicates. That is, once the first random number is calculated, it is removed from the possibilities for the next three numbers, and so on.
     
    jarvi, Feb 4, 2005 IP
  4. david_sakh

    david_sakh Peon

    Messages:
    1,225
    Likes Received:
    29
    Best Answers:
    0
    Trophy Points:
    0
    #4
    in this case you want to use some conditionals
    Since you are using only 4 nums, i guess it doesn't matter that this is inefficient:

    $doNotUse[0]=-1;
    $doNotUse[1]=-1;
    $doNotUse[2]=-1;
    $doNotUse[3]=-1;
    for ($i=0;$i<$3;$i++) {
    $rand=-1;
    while ($rand[$i]!=$doNotUse[0] && $rand[$i]!=$doNotUse[1] && $rand[$i]!=$doNotUse[2] && $rand[$i]!=$doNotUse[3])
    $rand=mt_rand(1,10);
    num[$i]=$rand;
    $doNotUse[$i]=$rand;
    }
     
    david_sakh, Feb 4, 2005 IP
  5. rvarcher

    rvarcher Peon

    Messages:
    69
    Likes Received:
    4
    Best Answers:
    0
    Trophy Points:
    0
    #5
    or even...

    
    $arr = array();
    while ( count($arr) < 10 ) {
        $x = mt_rand(1,10); 
        if ( !in_array($x,$arr) ) { $arr[] = $x; echo "$x<br>"; }
    }
    
    PHP:
    See it in action here (for a limited time):
    http://www.tropicrentals.com/test.php
     
    rvarcher, Feb 4, 2005 IP
  6. david_sakh

    david_sakh Peon

    Messages:
    1,225
    Likes Received:
    29
    Best Answers:
    0
    Trophy Points:
    0
    #6
    damn you and your greater knowledge of functions!

    in_array! blarggh! :D

    I really should start reading a php function list or manual some day....
     
    david_sakh, Feb 4, 2005 IP
  7. jarvi

    jarvi Well-Known Member

    Messages:
    127
    Likes Received:
    1
    Best Answers:
    0
    Trophy Points:
    103
    #7
    Thank you, exactly what I was looking for. Feel free to remove the test page if you want.
     
    jarvi, Feb 4, 2005 IP
  8. mattm591

    mattm591 Peon

    Messages:
    2
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #8
    How could I use this to get four different variables
    number1$
    number2$
    number3$
    number4$
    not just
    number$

    Thanks
     
    mattm591, Apr 3, 2005 IP
  9. david_sakh

    david_sakh Peon

    Messages:
    1,225
    Likes Received:
    29
    Best Answers:
    0
    Trophy Points:
    0
    #9
    a modified version of rvarchers code should do the trick:

    
    $arr = array();
    $i=0;
    $result = array();
    while ( count($arr) < 6 ) {
        $x = mt_rand(1,10);
        if ( !in_array($x,$arr) ) {$result[$i] = $x;$i+=1;}
    }
    
    PHP:
    $result should hold four values.
     
    david_sakh, Apr 3, 2005 IP
  10. mattm591

    mattm591 Peon

    Messages:
    2
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #10
    There seems to be some problem with this as the maximum execution time of 30 secs is exceeded everytime.
     
    mattm591, Apr 3, 2005 IP
  11. GeorgeB.

    GeorgeB. Notable Member

    Messages:
    5,695
    Likes Received:
    288
    Best Answers:
    0
    Trophy Points:
    280
    #11
    PHP owns in the deuce double 0 fife!
     
    GeorgeB., Apr 3, 2005 IP
  12. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #12
    <?php
            srand((float) microtime() * 10000000);
            $arrsize = 10;
            for($index = 0; $index < $arrsize; $index++)
                    $array[$index] = $index;
            $keys = array_rand($array, count($array));
            for($index = 0; $index < $arrsize; $index++)
                    echo sprintf("%d<br>", $array[$keys[$index]]);
    ?>
    PHP:
    Skipping previous randomly-generated values will always be CPU-intensive and may take some time to execute. This script will take same time every time you run it.

    J.D.
     
    J.D., Apr 3, 2005 IP
  13. dtan

    dtan Peon

    Messages:
    25
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #13
    Since you are using a small range of unique numbers, I suggest the following:

    1 Create an array of 10 integers with value 1-10.
    $array[0] = 1
    $array[1] = 2 etc. . .

    2 Retrieve a random integer between 0-9 which will act as the index to the array.
    $index

    3 Switch the values of the array[0] and array[$index].

    4 Repeat steps 2 and 3 but increment the minimum value by 1. So the random integer will between 1-9 and the switched array index will be 1. . .on the next loop 2 etc. . .

    Then return the first four integers in the array. This will run in constant time.

    dtan
     
    dtan, Apr 12, 2005 IP
  14. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #14
    Wouldn't the correct introduction rather be "the algorithm in the post above works this way..."?

    J.D.
     
    J.D., Apr 12, 2005 IP
  15. dtan

    dtan Peon

    Messages:
    25
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #15
    mmm sarcasm. Sorry that I wasn't aware of the internals of array_rand.

    Why would you say its cpu intensive? It should take very little time to run. . .especially with an upper limit of 10 numbers and 4 unique randoms. . .
    The algorithm should always run in constant time. It is bounded by the number of uniques you seek. Furthermore for each loop there are only 2 assignments.

    Looking at it again, it is only the same when the number of uniques to be returned is equal to the upper limit. . .
     
    dtan, Apr 12, 2005 IP
  16. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #16
    I was referring to some posts at the beginning of the thread; that is, those that suggested to generate a number and then lookup it up in the existing array. All of what's involved in this process requires CPU (i.e. generating random numbers, in-memory lookups, array modification, etc), large arrays and significant number of requests will put unnecessary strain on the CPU.

    My understanding is that this is how it works (i.e. that if you request more than one key, no duplicates will be returned). If anybody has any evidence to the contrary, then an algorithm similar to what you describe can be used, as well as some other (e.g. with an associative array or a linked list you can just remove selected entries and use the remaining entries for the next selection instead of swapping elements).

    J.D.
     
    J.D., Apr 12, 2005 IP
  17. LGRComp

    LGRComp Well-Known Member

    Messages:
    516
    Likes Received:
    27
    Best Answers:
    0
    Trophy Points:
    195
    #17
    Try this. It is quick and easy.

    $numbers=array(1,2,3,4,5,6,7,8,9,10);

    //Get 4 unique random keys from $numbers array.
    $rand_keys = array_rand($numbers, 4);

    //if you want to sort the random keys
    sort($rand_keys);

    //print out the random numbers using the
    //random keys.
    foreach ($rand_keys as $k=>$v) {
    echo $numbers[$v].", ";
    }
     
    LGRComp, Apr 14, 2005 IP
    Allinpoker.cc likes this.
  18. J.D.

    J.D. Peon

    Messages:
    1,198
    Likes Received:
    65
    Best Answers:
    0
    Trophy Points:
    0
    #18
    How's what you are suggesting different from a few posts above?
     
    J.D., Apr 14, 2005 IP
  19. david_sakh

    david_sakh Peon

    Messages:
    1,225
    Likes Received:
    29
    Best Answers:
    0
    Trophy Points:
    0
    #19
    this has turned into an outright pissing contest :D

    I shouldn't even have entered. :eek:
     
    david_sakh, Apr 14, 2005 IP
  20. JDM

    JDM Peon

    Messages:
    1
    Likes Received:
    0
    Best Answers:
    0
    Trophy Points:
    0
    #20
    I am using this code snippet to display random images along with thier linking codes on a large site...since I reuse this code in other sections of the site i would like to eliminate duplicate appearances...is there any way to do this with this code?

    <?php
    $file ="potd.txt";
    $x = file("$file");
    $y = mt_rand(0, sizeof($x)-1);
    echo $x[$y];
    ?>

    Thanx in Advance!
     
    JDM, Dec 29, 2005 IP