JM4
JM4

Reputation: 6788

Random ID/Number Generator in PHP

I am building a list of "agent id's" in my database with the following requirements:

  1. The ID must be 9 digits long (numeric only)
  2. The ID may not contain more than 3 of the same number.
  3. The ID may not contain more than 2 of the same number consecutively (i.e. 887766551; cannot have 888..)

So far I have part 1 down solid but am struggling with 2 and 3 above. My code is below.

function createRandomAGTNO() {
    srand ((double) microtime( )*1000000);
    $random_agtno = rand(100000000,900000000);
    return $random_agtno;
}

// Usage
$NEWAGTNO = createRandomAGTNO();

Any ideas?

Upvotes: 0

Views: 4486

Answers (4)

Poni
Poni

Reputation: 11317

Try this code:

<?php
function createRandomAGTNO() {
    //srand ((double) microtime( )*1000000);
    $digits = array( 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ,1, 2, 3, 4, 5, 6, 7, 8, 9, 0 );
    shuffle($digits);
    $random_agtno = 0;
    for($i = 0; $i < 9; $i++)
    {
        if($i == 0)
        {
            while($digits[0] == 0)
                shuffle($digits);
        }
        /*if($i >= 2)
        {
            while(($random_agtno % 100) == $digits[0])
                shuffle($digits);
        }*/
        $random_agtno *= 10;
        $random_agtno += $digits[0];
        array_splice($digits, 0, 1);
    }
    return $random_agtno;
}

for($i = 0; $i < 1000; $i++)
{
    $NEWAGTNO = createRandomAGTNO();
    echo "<p>";
    echo $NEWAGTNO;
    echo "</p>";
}
?>

Good luck!

Edit: Removed the call to srand() and commented-out the "if($i >= 2)" code, which is impossible anyway, here.

Upvotes: 0

hobbs
hobbs

Reputation: 239682

  1. Do not re-seed the RNG on every call like that, unless you want to completely blow the security of your random numbers.
  2. Unless your PHP is very old, you probably don't need to re-seed the RNG at all, as PHP seeds it for you on startup and there are very few cases where you need to replace the seed with one of your own choosing.
  3. If it's available to you, use mt_rand instead of rand. My example will use mt_rand.

As for the rest -- you could possibly come up with a very clever mapping of numbers from a linear range onto numbers of the form you want, but let's brute-force it instead. This is one of those things where yes, the theoretical upper bound on running time is infinite, but the expected running time is bounded and quite small, so don't worry too hard.

function createRandomAGTNO() {
  do {
    $agt_no = mt_rand(100000000,900000000);
    $valid = true;
    if (preg_match('/(\d)\1\1/', $agt_no))
      $valid = false; // Same digit three times consecutively
    elseif (preg_match('/(\d).*?\1.*?\1.*?\1/', $agt_no))
      $valid = false; // Same digit four times in string
  } while ($valid === false);
  return $agt_no;
}

Upvotes: 7

Justin Lucas
Justin Lucas

Reputation: 2321

The first solution that comes to mind is a recursive function that simply tests your three requirements and restarts if any three of them fail. Not the most efficient solution but it would work. I wrote an untested version of this below. May not run without errors but you should get the basic idea from it.

function createRandomAGTNO(){
  srand ((double) microtime( )*1000000);
  $random_agtno = rand(100000000,900000000);

  $random_agtno_array = explode('', $random_agtno);

  foreach($random_agtno_array as $raa_index => $raa){
    if($raa == $random_agtno_array[$raa_index + 1] && raa == $random_agtno_array[$raa_index + 2]) createRandomAGTNO();

    $dup_match = array_search($raa, $random_agtno_array);
    if($dup_match){
      unset($random_agtno_array[$dup_match]);
      if(array_search($raa, $random_agtno_array)) createRandomAGTNO();
    };
  }

  return $random_agtno;
}

Upvotes: 0

Piotr M&#252;ller
Piotr M&#252;ller

Reputation: 5548

For second condition, you can create an array like this

$a = array( 0,0,1,1,2,2,3,3.....,9,9 );

and get random elements: array_rand() (see manual) to get digit, append it to your ID and remove value from source array by unsetting at index.

Generally, this solving also third condition, but this solution excludes all ID's with possible and acceptable three digits

Upvotes: 1

Related Questions