Solved

Generating a list of unique random number with PHP

Posted on 2006-06-15
15
527 Views
Last Modified: 2008-03-17
Hi,

I would like to generate a list of 500,000 unique random numbers that will be printed on coupons.
The numbers it generates must have a prefix "MLX" before a 9 digit number (MLX846795265).

How can I produce this list of unique random numbers and print all 500,000 numbers on a .TXT file

I found this script that seems to partially do the job.  How can I modify it to print 500,000 unique numbers on a text file?

Please let me know.

Thanks,
-L.


<?
function generateRandomNumber($digits){

$characters = "0123456789";
$returnValue = "";

for($no=0;$no<$digits;$no++){

$randValue = mt_rand(0,(strlen($characters)-1));
$returnValue.=substr($characters,$randValue,1);
}

return $returnValue;
}

echo "MLX".generateRandomNumber(9);

?>
0
Comment
Question by:lollodev
  • 11
  • 4
15 Comments
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16910091
<?php

function generateRandomNumbers($i_number_of_digits, $i_number_of_results, &$a_results)
      {
      $a_results = array();
      $i_max = (int)str_repeat('9', $i_number_of_digits);
      while ($i_number_of_results !== 0)
            {
            $i_random_value = str_pad(rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT);
            if (!in_array($i_random_value, $a_results))
                  {
                  $a_results[] = $i_random_value;
                  $i_number_of_results--;
                  }
            }
      }

generateRandomNumbers(9, 100, $a_random_numbers);
print_r($a_random_numbers);
echo count($a_random_numbers) . "\n";
echo count(array_unique($a_random_numbers)) . "\n";
?>

generates output of ...

Array
(
    [0] => 256866455
    [1] => 484558105
    [2] => 849822998
    [3] => 273071289
    [4] => 829010009
    [5] => 410705566
    [6] => 112396241
    [7] => 956054687
    [8] => 086700440
    [9] => 061462403
    [10] => 357391358
    [11] => 723022461
    [12] => 498687744
    [13] => 530578613
    [14] => 803558349
    [15] => 417724609
    [16] => 033721924
    [17] => 411804199
    [18] => 169647217
    [19] => 383911133
    [20] => 160552979
    [21] => 798889160
    [22] => 674407959
    [23] => 465332031
    [24] => 847930908
    [25] => 285583496
    [26] => 036590577
    [27] => 005737305
    [28] => 564605713
    [29] => 965637207
    [30] => 474945068
    [31] => 848876953
    [32] => 279327393
    [33] => 432800293
    [34] => 708221435
    [35] => 338500977
    [36] => 460845947
    [37] => 780822754
    [38] => 955169677
    [39] => 318359375
    [40] => 077911377
    [41] => 603454590
    [42] => 934539794
    [43] => 132202149
    [44] => 599273682
    [45] => 994445800
    [46] => 865081787
    [47] => 623779297
    [48] => 993682861
    [49] => 547546387
    [50] => 465545654
    [51] => 136840821
    [52] => 729888916
    [53] => 356506348
    [54] => 954681396
    [55] => 515136719
    [56] => 776641845
    [57] => 015075684
    [58] => 051239014
    [59] => 102416993
    [60] => 602691650
    [61] => 617004394
    [62] => 973968505
    [63] => 742431640
    [64] => 176788330
    [65] => 756042480
    [66] => 441619873
    [67] => 778930664
    [68] => 967681884
    [69] => 525939941
    [70] => 672943115
    [71] => 055664063
    [72] => 944122314
    [73] => 520446777
    [74] => 386688233
    [75] => 916381836
    [76] => 574859619
    [77] => 833312988
    [78] => 801605224
    [79] => 204833985
    [80] => 828643798
    [81] => 058288575
    [82] => 636444092
    [83] => 264770508
    [84] => 174224854
    [85] => 289123535
    [86] => 109954834
    [87] => 939941406
    [88] => 580352783
    [89] => 119567871
    [90] => 940887451
    [91] => 574096680
    [92] => 515777588
    [93] => 643371582
    [94] => 347991944
    [95] => 010986329
    [96] => 949249267
    [97] => 454284668
    [98] => 050018311
    [99] => 594360351
)
100
100
0
 

Author Comment

by:lollodev
ID: 16911119
Hi RQuadling ,

Thanks for your response.  
I tried your script and it works up until 10,000 unique numers but I can't manage to generate 500,000 numbers. I tried with the set_time_limit() function but it will still go in time-out.

My other question was on how to print the numbers with the "MLX" prefix on a txt file.

Please let me know.

<?php
set_time_limit(300);
function generateRandomNumbers($i_number_of_digits, $i_number_of_results, &$a_results){
$a_results = array();
$i_max = (int)str_repeat('9', $i_number_of_digits);
while ($i_number_of_results !== 0)
{
$i_random_value = str_pad(rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT);
if (!in_array($i_random_value, $a_results))
{
$a_results[] = $i_random_value;
$i_number_of_results--;
}
}
}

generateRandomNumbers(9, 500000, $a_random_numbers);
print_r($a_random_numbers);
echo count($a_random_numbers) . "\n";
echo count(array_unique($a_random_numbers)) . "\n";
?>
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16911168
Sorry.

<?php
// Allow the script to run forever.
set_time_limit(0);

function generateRandomNumbers($i_number_of_digits, $i_number_of_results, &$a_results)
      {
      $a_results = array();
      $i_max = (int)str_repeat('9', $i_number_of_digits);
      while ($i_number_of_results !== 0)
            {
            $i_random_value = 'MLX' . str_pad(rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT);
            if (!in_array($i_random_value, $a_results))
                  {
                  $a_results[] = $i_random_value;
                  $i_number_of_results--;
                  }
            }
      }

generateRandomNumbers(9, 500000, $a_random_numbers);
echo count($a_random_numbers) . "\n";
echo count(array_unique($a_random_numbers)) . "\n";
?>

Takes a while.
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16911233
This may be faster ...

function generateRandomNumbers($i_number_of_digits, $i_number_of_results, &$a_results)
      {
      $a_results = array();
      $i_max = (int)str_repeat('9', $i_number_of_digits);
      while (count($a_results) !== $i_number_of_results)
            {
            $a_results['MLX' . str_pad(rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT)] = count($a_results);
            }
      $a_results = array_keys($a_results);
      }

I'm currently testing this. Old code has taken 10 minutes and counting.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16911365
It seems that the second method is faster over 1000 but at 5000 the first method was faster.

So, try both. See which you prefer. If speed is not an issue then I suppose it doesn't matter.
0
 

Author Comment

by:lollodev
ID: 16911467
I'm still testing the first method.  Can't manage to have the second one working...but time isn't an issue anyways.

How can I print the numbers to a txt file without the array brackets (Array ( [0] =>) ?

Thanks,
-L.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16911499
Change

generateRandomNumbers(9, 500000, $a_random_numbers);

to ...

(PHP5)
foreach(generateRandomNumbers(9, 500000, $a_random_numbers) as $s_random_value)
 {
 file_put_contents('./random.txt', "$s_random_value\n", FILE_APPEND);
 }

(PHP4)
$fp = fopen('./random.txt', 'wt');
foreach(generateRandomNumbers(9, 500000, $a_random_numbers) as $s_random_value)
 {
 fwrite($fp, "$s_random_value\n");
 }
fclose($fp);


0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16911506
If you are running this from the command line, then you could use ...

foreach(generateRandomNumbers(9, 500000, $a_random_numbers) as $s_random_value)
 {
 echo "$s_random_value\n";
 }


and capture the output using normal shell redirection ...

php random.php > random.txt
0
 

Author Comment

by:lollodev
ID: 16911690
I get an error on the foreach statement.
I'm still running the first script....hope it is almost over.

<?php
// Allow the script to run forever.
set_time_limit(0);


function generateRandomNumbers($i_number_of_digits, $i_number_of_results, &$a_results)

{
$a_results = array();
$i_max = (int)str_repeat('9', $i_number_of_digits);
while ($i_number_of_results !== 0)
{
$i_random_value = 'MLX' . str_pad(rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT);
if (!in_array($i_random_value, $a_results))
{
$a_results[] = $i_random_value;
$i_number_of_results--;
}
}
}
$fp = fopen('./random.txt', 'wt');

foreach(generateRandomNumbers(9, 50, $a_random_numbers) as $s_random_value)
{
fwrite($fp, "$s_random_value\n");
}
fclose($fp);
?>
0
 
LVL 40

Accepted Solution

by:
Richard Quadling earned 500 total points
ID: 16911856
Doh. Of course you would! Sorry. I tend to return true/false from most of my functions.

<?php
// Allow the script to run forever.
set_time_limit(0);

function generateRandomNumbers($i_number_of_digits, $i_number_of_results)
      {
      $a_results = array();
      $i_max = (int)str_repeat('9', $i_number_of_digits);
      while (count($a_results) !== $i_number_of_results)
            {
            $a_results['MLX' . str_pad(rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT)] = count($a_results);
            }
      return array_flip($a_results);
      }

$fp = fopen('./random.txt', 'wt');
foreach(generateRandomNumbers(9, 50) as $s_random_value)
      {
      fwrite($fp, "$s_random_value\n");
      }
fclose($fp);
?>
0
 

Author Comment

by:lollodev
ID: 16912229
Beautiful!  

I run the script for 500,000 and in about 45 seconds it printed 499,894 unique numbers!

Just out of curiosity, why doesn't it print exactly 500.000 numbers?  This is not an issue, I'm just curious to understand.

Thanks,
-L.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16918695
Really?

It should have done!!!!

And 45 seconds! WOW! What are you running on? 50,000 is taking ages on mine.

Ah. I added some debugging.

The second version hangs dead at 32768 entries.

Ah. On Windows, rand is limited to 32768. DOH.

Use mt_rand instead.

Now. My random numbers are generated and saved in around 13 seconds. Hey! That's better.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16918716
Right. Some tests.

The second method is CONSIDERABLY faster than the first as only the keys are checked.

<?php
// Allow the script to run forever.
set_time_limit(0);

function generateRandomNumbers($i_number_of_digits, $i_number_of_results)
      {
      $a_results = array();
      $i_max = (int)str_repeat('9', $i_number_of_digits);
      $i_count = $i_number_of_results;
      while (count($a_results) !== $i_number_of_results)
            {
            $s_random = 'MLX' . str_pad(mt_rand(1, $i_max), $i_number_of_digits, '0', STR_PAD_LEFT);
            if (!isset($a_results[$s_random]))
                  {
                  $a_results[$s_random] = $i_count--;
                  }
            }
      return array_flip($a_results);
      }

$fp = fopen('./random.txt', 'wt');
$s_output = implode("\n", generateRandomNumbers(9, 500000));
fwrite($fp, $s_output);
fclose($fp);
?>

0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16918719
In my tests, EXACTLY 500,000 unique lines were outputted. I can see no reason why the file is not right. Try the new code above to see if this is any better for you.
0
 
LVL 40

Expert Comment

by:Richard Quadling
ID: 16918728
Also, rand produced 32768 random values before duplicating. mt_rand will produce duplicate answers but these are rejected using the code.
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
These days socially coordinated efforts have turned into a critical requirement for enterprises.
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to count occurrences of each item in an array.

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question