2012-03-21 111 views
2

我需要一個隨機化一個類似於隨機播放的數組的函數,不同的是每個元素有不同的機會。如何在php中做一個特殊的隨機播放功能

例如,考慮下面的數組:

$animals = array('elephant', 'dog', 'cat', 'mouse'); 

象有越來越上比狗第一指標的機會較高。狗比貓有更高的機會等等。例如,在這個特殊的例子中,大象可能有40%的機會獲得第一名,30%的獲得第二名,20%獲得第三名,10%獲得最後一名。

所以,在洗牌之後,原始數組中的第一個元素將更有可能(但不是肯定)處於第一個位置,最後一個位於最後位置。

+2

一個有趣的問題,但是爲結束在每個位置的每個元素分配概率的機制是刑事規定不足的。 – Jon 2012-03-21 19:33:04

+0

例如10%以下會發生什麼? – Cyclone 2012-03-21 19:35:18

+0

在這種情況下,大象有10%的機會在最後的位置,90%的機會不在最後的位置。 – 2012-03-21 19:46:39

回答

5

正常洗牌可以實現同樣

  • 在一定範圍內
  • 掉落物品隨機從左至右
接他們

我們可以調整滴落步驟,將每個元素都放到整個範圍內,但是在某些位置ding窗口。假設N是數組中元素的數量,窗口寬度將是w,我們將在每個步驟將其移動off。然後off*(N-1) + w將是範圍的總寬度。

這是一個函數,它扭曲元素的位置,但不是完全隨機的。

function weak_shuffle($a, $strength) { 
    $len = count($a); 
    if ($len <= 1) return $a; 
    $out = array(); 
    $M = mt_getrandmax(); 
    $w = round($M/($strength + 1)); // width of the sliding window 
    $off = ($M - $w)/($len - 1); // offset of that window for each step. 
    for ($i = 0; $i < $len; $i++) { 
     do { 
      $idx = intval($off * $i + mt_rand(0, $w)); 
     } while(array_key_exists($idx, $out)); 
     $out[$idx] = $a[$i]; 
    } 
    ksort($out); 
    return array_values($out); 
} 
  • $strength = 0〜正常洗牌。
  • $strength = 0.25〜你想要的結果(40.5%,25.5%,22%,爲elephant 12%)
  • $strength = 1第一個項目將永遠最後一個之後。
  • $strength >= 3陣列實際上從來沒有洗牌

遊樂場來進行測試:

$animals = array('elephant', 'dog', 'cat', 'mouse'); 
$pos = array(0,0,0,0); 
for ($iter = 0; $iter < 100000; $iter++) { 
    $shuffled = weak_shuffle($animals, 0.25); 
    $idx = array_search('elephant', $shuffled); 
    $pos[$idx]++; 
} 
print_r($pos); 
+0

+1,非常好的方法。可惜它有一個非確定性的運行時間。 – Jon 2012-03-21 21:18:53

+0

@Jon首先,'mt_getrandmax'返回2^31-1,因此在小陣列上衝突*幾乎不可能。其次,解決同樣的關鍵結果可能會以某種確定性的順序進行。例如。 '先進先出'或收集所有值相同的密鑰進入數組,然後...洗牌;-) – kirilloid 2012-03-21 21:48:29

+0

非常感謝@Kirilloid,這真是一個聰明的解決方案,並服務於我的目的。你甚至可以給它一個力量,真的很好。 – 2012-03-22 11:25:24

2

嘗試使用此算法:

$animals = [ 'elephant', 'dog', 'cat', 'mouse' ]; // you can add more animals here 
$shuffled = []; 

$count = count($animals); 

foreach($animals as $chance => $animal) { 
    $priority = ceil(($count - $chance) * 100/$count); 
    $shuffled = array_merge($shuffled, array_fill(0, $priority, $animal)); 
} 

shuffle($shuffled); 
$animals = array_unique($shuffled); 
1

您有一個數組,假設n個元素。第i個元素到第j個位置的概率是P(i,j)。如果我的理解很好,下面的公式成立:

(P(i1, j1) >= P(i2, j2)) <=> (|i1 - j1| <= |j1 - i1|) 

因此,你有你的數組中距離和洗牌概率之間的伽羅瓦連接。你可以使用這個伽羅瓦連接來實現你的確切公式,如果你有。如果你沒有公式,你可以創造一個公式,它將符合上述標準。祝你好運。