An array of random numbers with a range of values of a certain amount of php

The task is to create an array of random numbers of a certain length, with a given range of numbers, so that the sum has a certain value. For example, you need 5 numbers, with a range of 5-20, for a total of 50. The output needs something like 6, 12, 13, 8, 11.

For those who will be looking for a solution to such a problem, so far the only one (you can immediately pick it up for yourself):

function array_rand_with_sum($min, $max, $sum, $num)
{
   $a = array();
   if ($max*$num > $sum && $min < $sum\$num)
   {
      do
      {
         for($i = 0; $i < $num; $i ++)
         {
            $a[$i] = mt_rand($min, $max);
         }
      }
      while(array_sum($a) != $sum);
      return $a;
   }
   else { return "Ошибка! Проверьте входные данные."; }
}

If someone finds a better one, I will be very happy!

Author: Nick Volynkin, 2015-05-13

2 answers

To hope that your function will terminate rather recklessly, try these input parameters:

array_rand_with_sum(1, 1000, 10000, 200);

I have never managed to get a result out of a dozen attempts.

My version of the function is something like this:

function array_rand_with_sum($min, $max, $sum, $num)
{
    if ($num <= 0 || $max * $num < $sum || $min * $num > $sum) {
        return "Ошибка! Проверьте входные данные.";
    }
    if ($num == 1) {
        return [$sum];
    }
    $rand = mt_rand(
        max($min, $sum - $max * ($num - 1)),
        min($max, $sum - $min * ($num - 1))
    );
    $res = array_rand_with_sum($min, $max, $sum - $rand, $num - 1);
    $res[] = $rand;
    return $res;
}

$res = array_rand_with_sum(1, 1000, 10000, 200);
if (is_array($res)) {
    var_dump([
        'min' => min($res),
        'max' => max($res),
        'sum' => array_sum($res),
        'count' => count($res),
    ]);
}
var_dump($res);
 2
Author: actofgod, 2015-05-14 09:57:33

Not pretty, but as an option

    function array_rand_with_sum($min, $max, $sum, $num)
{
    $return = array();
    $newsum = $sum;
    for($i=0;$i<$num;$i++) {
        $c = rand($min,($max<$newsum)?$max:$newsum);
        $newsum -= $c;
        $return[]= $c;
    }
    $array_sum = array_sum($return);
    arsort($return);
    if($array_sum>$sum) {
        $return[0]-= ($array_sum-$sum);
    } else {
        $return[count($return)-1]+= ($sum-$array_sum);
    }
    return $return;
}
 -1
Author: Mike, 2015-05-14 07:31:23