0

I would like to generate a given number of random numbers with given constraints. Here, I would like the difference between every other element to be at least (say) 3 and the (generated) number to fall within a given range.

I have found a function to generate a given number of random numbers in a given range (Generating UNIQUE Random Numbers within a range):

function UniqueRandomNumbersWithinRange($min, $max, $quantity) {
    $numbers = range($min, $max);
    shuffle($numbers);
    return array_slice($numbers, 0, $quantity);
}
print_r( UniqueRandomNumbersWithinRange(0,25,5) );

which gives:

Array
(
    [0] => 20
    [1] => 23
    [2] => 7
    [3] => 18
    [4] => 17
)

and does not meet the requirements. Instead

Array
(
    [0] => 20
    [1] => 24
    [2] => 2
    [3] => 12
    [4] => 8
)

would work.

Is there a simple way to do that in PHP ?

Best,

chac1
  • 5
  • 2

1 Answers1

1
  • Generate a random seed value between $min and $max.
  • Collect all numbers less than $seed which has differences greater than or equal to $min_diff(say 3). Stop at $min.
  • Collect all numbers greater than $seed which has differences greater than or equal to $min_diff(say 3). Stop at $max.
  • Shuffle the numbers.
  • Return the array_slice() with the required quantity.
  • If constraint cannot be fulfilled, throw an exception.

Snippet:

<?php

function UniqueRandomNumbersWithinRange($min, $max, $quantity ,$min_diff = 3) {
    $rand_seed = rand($min,$max);
    $numbers = [];
    $curr = $rand_seed;
    while($curr >= $min){
        $numbers[] = $curr;
        $curr -= $min_diff;
    }
    
    $curr = $rand_seed;
    while($curr <= $max){
        $curr += $min_diff;
        if($curr <= $max) $numbers[] = $curr;
    }
    shuffle($numbers);
    if(count($numbers) < $quantity){
        throw new Exception("Constraints cannot be fulfilled with given quantity: $quantity and given min. diff.:$min_diff");
    }
    return array_slice($numbers, 0, $quantity);
}

print_r( UniqueRandomNumbersWithinRange(0,25,5) ); 
nice_dev
  • 17,053
  • 2
  • 21
  • 35