Создавайте числа в массиве, которые суммируются до заданной суммы

Я новичок в программировании на PHP. Таким образом, в основном, что мне нужно выполнить, создайте массив из x чисел (созданных случайным образом), значение которых добавляется к n:

Скажем, мне нужно создать 4 числа, которые составляют до 30. Мне просто нужен первый случайный набор данных. Здесь 4 и 30 являются переменными, которые будут заданы пользователем.

По существу что-то вроде

x = amount of numbers;
n = sum of all x combined;

// create x random numbers which all add up to n;

$row = array(5, 7, 10, 8) // these add up to 30

Кроме того, дубликаты не допускаются, и все числа должны быть целыми положительными.

Мне нужны значения в массиве. Я когда-то общался с ним, однако мои знания довольно ограничены. Любая помощь будет оценена.

Ответы

Ответ 1

Во-первых, это действительно крутая проблема. Я почти уверен, что мой подход даже не распространяет числа отлично, но он должен быть лучше, чем некоторые другие подходы здесь.

Я решил построить массив с самого низкого номера (и перетасовать их в конце). Это позволяет мне всегда выбирать случайный диапазон, который позволит получить допустимые результаты. Поскольку числа всегда должны увеличиваться, я решал для максимально возможного числа, что гарантирует, что действительное решение все еще существует (т.е. Если n = 4 и max = 31, если первое число было выбрано равным 7, то оно не будет можно выбрать числа больше 7, так что сумма из 4 чисел будет равна 31).

$n = 4;
$max = 31;
$array = array();

$current_min = 1;
while( $n > 1 ) {
    //solve for the highest possible number that would allow for $n many random numbers
    $current_max = floor( ($max/$n) - (($n-1)/2) );
    if( $current_max < $current_min ) throw new Exception( "Can't use combination" );
    $new_rand = rand( $current_min, $current_max ); //get a new rand
    $max -= $new_rand; //drop the max
    $current_min = $new_rand + 1; //bump up the new min
    $n--; //drop the n
    $array[] = $new_rand; //add rand to array
}
$array[] = $max; //we know what the last element must be
shuffle( $array );

EDIT: при больших значениях $n вы получите множество сгруппированных значений в конце массива, так как есть хорошая вероятность, что вы получите случайное значение около максимального значения, заставляя остальных быть очень близко друг к другу. Возможное исправление состоит в том, чтобы иметь взвешенный rand, но это вне меня.

Ответ 2

Я не уверен, правильно ли я вас понял, но попробуйте следующее:

$n = 4;
$max = 30;
$array = array();

do {
    $random = mt_rand(0, $max);

    if (!in_array($random, $array)) {
        $array[] = $random;
        $n--;
    }
} while (n > 0);

Ответ 3

Извините, я пропустил "без дубликатов" тоже - Нужно зацепиться за "дедупликатор"... я помещаю его в другой question

Для генерации ряда случайных чисел с фиксированной суммой:

  • сделать серию случайных чисел (наибольшей практической величины, чтобы скрыть гранулярность...)
  • вычислить их сумму
  • умножайте каждый последовательно по желаемому/сумме

(в основном для масштабирования случайной серии до ее нового размера)

Затем для корректировки для ошибки:

  • пересчитать сумму и ее разницу от желаемой суммы
  • добавить sumdiff к случайному элементу последовательно, если это не приводит к отрицательный, если он делает петлю к другому случайный элемент до штрафа.
  • чтобы быть ультратонким, вместо этого добавьте или вычесть 1 бит на случайные элементы пока sumdiff = 0

Некоторая неслучайность, возникающая в результате этого, заключается в том, что величина исходных рандомов слишком мала, что приводит к детализации результата.

У меня нет php, но вот выстрел -

$n = ;              //size of array
$targsum = ;        //target sum
$ceiling = 0x3fff;  //biggish number for rands
$sizedrands = array();

$firstsum=0;
$finsum=0;

//make rands, sum size
for( $count=$n; $count>0; $count--)
{ $arand=rand( 0, $ceiling );
  $sizedrands($count)=$arand;
  $firstsum+=$arand; }

//resize, sum resize
for( $count=$n; $count>0; $count--)
{ $sizedrands($count)=($sizedrands($count)*$targsum)/$firstsum;
  $finsum+=$sizedrands($count);
  }

//redistribute parts of rounding error randomly until done
$roundup=$targsum-$finsum;

$rounder=1; if($roundup<0){ $rounder=-1; }

while( $roundup!=0 )
{ $arand=rand( 0, $n );
  if( ($rounder+$sizedrands($arand) ) > 0 )
  { $sizedrands($arand)+=$rounder; 
    $roundup-=$rounder; }
  }

Ответ 4

Надеюсь, это поможет вам больше....

Approch-1

$aRandomarray = array();
for($i=0;$i<100;$i++)
{
    $iRandomValue = mt_rand(1000, 999);
    if (!in_array($iRandomValue , $aRandomarray)) {
        $aRandomarray[$i] = $iRandomValue;
    }
} 

Approch-2

$aRandomarray = array();
for($i=0;$i<100;$i++)
{
    $iRandomValue = mt_rand(100, 999);
    $sRandom .= $iRandomValue;
}
array_push($aRandomarray, $sRandom);