Solved

Generating a list of unique random number with PHP

Posted on 2006-06-15
15
526 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
Are your AD admin tools letting you down?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

 
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

Microsoft Certification Exam 74-409

Veeam® is happy to provide the Microsoft community with a study guide prepared by MVP and MCT, Orin Thomas. This guide will take you through each of the exam objectives, helping you to prepare for and pass the examination.

Question has a verified solution.

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

Developers of all skill levels should learn to use current best practices when developing websites. However many developers, new and old, fall into the trap of using deprecated features because this is what so many tutorials and books tell them to u…
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…
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

770 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