Yeni rasgele oluşturulan değerlerle dizisinde yinelenen değerleri değiştirin

2 Cevap php

Ben değerlerin n miktarı ile bir dizi oluşturur (bir previous question cevapsız gitti itibaren) bir fonksiyonu aşağıda var. Dizinin toplamı $ maksimum eşittir.

function randomDistinctPartition($n, $max) {
  $partition= array();
  for ($i = 1; $i < $n; $i++) {
    $maxSingleNumber = $max - $n;
    $partition[] = $number = rand(1, $maxSingleNumber);
    $max -= $number;
  }
  $partition[] = $max;
  return $partition;
}

Örneğin:. I $ n = 4 set ve varsa $ max = 30 Sonra aşağıdaki almalısınız.

array(5, 7, 10, 8);

Ancak, bu işlev hesap çiftleri ve 0'lar içine almaz. Ne istiyorum - ve gerçekleştirmek için çalışıyorlar - unique benim önceden belirlenmiş değişkene kadar eklemek sayılar $max ile bir dizi oluşturmak için olduğunu. No Duplicate numbers ve No 0 and/or negative integers.

2 Cevap

Tamam, bu sorun aslında lineer dizilerinin etrafında dönmektedir. 1 minimum değeri ile diziyi göz önünde bulundurun:

f(n) = 1 + 2 + ... + n - 1 + n

Böyle bir dizisinin toplamı eşittir:

f(n) = n * (n + 1) / 2

yani n = 4 için, bir örnek olarak, toplamı 10 olan 4 farklı numaralar hiçbir sıfır ile asgari toplam seçiyoruz ve hiçbir olumsuzluk 10 ise bu demektir Şimdi tersten gidin:.. Eğer 10 toplam ve varsa 4 sayı sonra tek bir combination (1,2,3,4) orada olduğunu.

Yani ilk sizin toplam alt sınır olarak en az yüksek olup olmadığını kontrol etmeniz gerekir. Daha az ise, hiçbir söz yok. Eşit ise, bir arada tam olarak mevcuttur. Eğer daha yüksek olursa daha karmaşık alır.

Şimdi kısıtlamaları 12 4 ile sayılar toplam vardır hayal. Biz f (4) = 10 olduğunu tespit ettik. Ama eğer ilk (en düşük) sayı 2 nedir?

2 + 3 + 4 + 5 = 14

Yani ilk sayı 1'den yüksek olamaz. Size ilk numarayı biliyorum. Şimdi 11 (12-1 olmak) toplam 3 sayı dizisi oluşturur.

1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12

İkinci sayı biri olamaz çünkü 2 olmak zorundadır. 3 ile başlayan, üç sayı minimum toplamı 12 ve biz 11 eklemek zorunda çünkü 3 olamaz.

3 mümkün olan en düşük olmak (2 - 1 - 12) Şimdi 9'a kadar eklemek iki numaralarını bulabilirsiniz.

3 + 4 = 7
4 + 5 = 9

Üçüncü sayı 3 veya 4 olabilir. Üçüncü sayı son sabittir bulundu ile. Iki olası kombinasyonlar:

1, 2, 3, 6
1, 2, 4, 5

Sen genel bir algoritma içine bu açabilirsiniz. Bu yinelenen bir uygulama düşünün:

$all = all_sequences(14, 4);
echo "\nAll sequences:\n\n";
foreach ($all as $arr) {
  echo implode(', ', $arr) . "\n";
}

function all_sequences($total, $num, $start = 1) {
  if ($num == 1) {
    return array($total);
  }
  $max = lowest_maximum($start, $num);
  $limit = (int)(($total - $max) / $num) + $start;
  $ret = array();
  if ($num == 2) {
    for ($i = $start; $i <= $limit; $i++) {
      $ret[] = array($i, $total - $i);
    }
  } else {
    for ($i = $start; $i <= $limit; $i++) {
      $sub = all_sequences($total - $i, $num - 1, $i + 1);
      foreach ($sub as $arr) {
        array_unshift($arr, $i);
        $ret[] = $arr;
      }
    }
  }
  return $ret;
}

function lowest_maximum($start, $num) {
  return sum_linear($num) + ($start - 1) * $num;
}

function sum_linear($num) {
  return ($num + 1) * $num / 2;
}

Çıktı:

All sequences:

1, 2, 3, 8
1, 2, 4, 7
1, 2, 5, 6
1, 3, 4, 6
2, 3, 4, 5

Bunun bir uygulama tüm dizileri almak ve rastgele birini seçmek için olacaktır. Bu, ya da ne yaptığınızı için yararlı veya gerekli olmayabilir eşit olası tüm kombinasyonları ağırlıklandırılarak avantajına sahiptir.

Bu, büyük toplamları veya yukarıda algoritma yerine her değer $limit ile $start aralığında rastgele elemanı döndürmek için değiştirilebilir, bu durumda elemanları, büyük sayılarla hantal hale gelecektir .

I would use 'area under triangle' formula... like cletus(!?) Im really gonna have to start paying more attention to things...

Neyse, ben bu çözüm, tüm elemanlar arasında istenen minimum aralık uygular eşit, özgün toplamı korumak için eşit boşluklar (dağıtım) terazi ve non-özyinelemeli (sıralama hariç) iş yapar, şimdi oldukça şık olduğunu düşünüyorum:

N uzunluğunda rasgele bir sayı dizisi () Verilen

Bir tür indeks s oluşturmak ()

ve kriteri aralıklarla bir (s (0))-a (s (1)), a (s (1))-a (s (2)), vb üzerinde çalışmak

  1. increase each interval by the desired minimum separation size eg 1 (this necessarily warps their 'randomness')

  2. decrease each interval by a factor calculated to restore the series sum to what it is without the added spacing.

Biz 1 ile dizi toplamını arttırmak dizisinin her * len 1 eklerseniz

1 added to each of series intervals increases sum by: len*(len+1)/2 //( ?pascal's triangle )

Taslak kodu:

$series($length);        //the input sequence 
$seriesum=sum($series);  //its sum
$minsepa=1;              //minimum separation

$sorti=sort_index_of($series) //sorted index - php haz function?

$sepsum=$minsepa*($length*($length+1))/2; 
//sum of extra separation

$unsepfactor100=($seriesum*100)/($seriesum+sepsum); 
//scale factor for original separation to maintain size
//(*100~ for integer arithmetic)

$px=series($sorti(0)); //for loop needs the value of prev serie

for($x=1 ; $x < length; $x++)
{ $tx=$series($sorti($x));             //val of serie to
  $series($sorti($x))= ($minsepa*$x)   //adjust relative to prev
                     + $px 
                     + (($tx-$px)*$unsepfactor100)/100; 

  $px=$tx;                             //store for next iteration 
  }
  • all intervals are reduced by a constant (non-random-warping-factor)
  • separation can be set to values other than one
  • implementantions need to be carefuly tweaked (i usualy test&'calibrate')
    to accomodate rounding errors. Probably scale everything up by ~15 then back down after. Intervals should survive if done right.

After sort index is generated, shuffle the order of indexes to duplicate values to avoid runs in the sequence of collided series. ( or just shuffle final output if order never mattered )

Safdilli Shuffle indeksler:

for($x=1; $x<$len; $x++)                   
{ if ($series($srt($x))==$series($srt($x-1)))
  { if( random(0,1) ) 
    { $sw= $srt($x);
      $srt($x)= $srt($x-1);
      $srt($x-1)= $sw;
  } } } 

Minimal rahatsızlık bir tür sadece gerekli minimum tarafından dupes ayrılık yerine, daha fazla soru tarafından aranan asgari-bazı 'rastgele' tutardan taşıyarak bir 'rastgele dizisi' için yapılabilir.

Burada kod yinelenen ya da değil, bu abartılı belki kindof evenhanded olmalı, ama olsun, dk ayrılması ile her eleman ayırır. Onlar için ve her kazıklandığı için + = minsep * (len-n) olarak sepsum hesaplanırken: kodu yalnızca serisi (n1 .. len) sorti (n0) bakarak dupes ayırmak için değiştirilmiş olabilir. Sonra ayar döngü sadece ayar uygulamadan önce kazıklandığı tekrar test etmek için vardır.