2012-02-04 78 views
1

我需要一個有效的算法來生成不同的組合(不允許重複)。每個組合有5個distint數字(不同的數字),範圍在1到99之間。結果必須存儲在一個數組中。如果可能的話,我希望允許定製的數字和範圍。數的順序並不重要(01 02 03 = 03 01 02)生成不同的組合PHP

Ex.: 
01 02 03 04 05 
02 03 04 05 06 
... 

有誰可以幫我建了嗎?我想從數組中挑選一些隨機組合。現在我使用mt_rand生成隨機組合,但它需要太多時間,所以很慢!我相信,發生在經常重複再花費時間來生成新的,新的...

+0

搜索費雪耶茨洗牌。 – 2012-02-04 02:25:40

+0

你知道你需要做多少內存嗎?來自199的5個獨特組合有71,523,144個。爲什麼你實際上需要知道每種可能的組合?幾乎肯定有更好的選擇,可以將它們全部用完......也許只是按照需要生成儘可能多的混搭版本,這肯定比71,523,144少得多。的 – 2012-02-04 11:31:21

+0

可能重複[如何降低循環速度(http://stackoverflow.com/questions/3109887/how-to-reduce-for-loop-speed) – 2012-02-04 11:41:49

回答

1

我把這個快起來,似乎工作。

<?php 

$range_low = 1; 
$range_hi = 99; 
$num_sets = 10; 

$set = generateSet($range_low, $range_hi, $num_sets); 

print_set($set); 

function generateSet($range_low, $range_hi, $numSets = 5, $numPerSet = 5) 
{ 
    $return = array(); 
    $numbers = array(); 

    for($i = $range_low; $i <= $range_hi; ++$i) { 
     $numbers[] = $i; 
    } 

    for ($s = 0; $s < $numSets; ++$s) { 
     $set = array_values($numbers); 
     shuffle($set); 

     $return[$s] = array(); 

     for ($i = 0; $i < $numPerSet; ++$i) { 
      $val = array_shift($set); 
      $return[$s][] = $val; 
     } 
    } 

    return $return; 
} 

function print_set($set) 
{ 
    foreach($set as $subset) { 
     foreach($subset as $value) { 
      echo str_pad($value, 2, '0', STR_PAD_LEFT) . ' '; 
     } 
     echo "\n"; 
    } 
} 

輸出示例:

90 75 89 43 57 
24 54 38 35 10 
77 21 55 33 83 
37 15 61 09 44 
25 31 85 17 20 
48 37 45 13 20 
82 70 74 64 72 
07 24 33 64 45 
34 13 39 33 05 
13 77 87 70 64 

要費雪耶茨洗牌陣列,看到this comment on shuffle你來代替洗牌的使用功能。

希望有所幫助。

+0

如問題所述,組合不允許重複。在1-99的情況下,它們很少會重複,但是如果你選擇1-10之類的東西,那麼你的代碼會產生很多重複的結果 – Ranty 2012-02-04 15:06:35

+0

它會將數值從數組中移開,因此它不能在同一組中重複,因爲值將從數組中刪除,不能再次選取。 – drew010 2012-02-04 19:47:11

+0

我不是說集合中的同一個數字。我說它會產生相同的組合。 – Ranty 2012-02-05 00:13:17

1

如果你真的絕對需要的全套每一個可能的組合:

function combinations($set,$length) { 
    $combinations = array(); 

    $setCount = count($set); 
    for($i = 0, $n = $setCount; $i <= ($n - $length); $i++) { 
    $combination = array(); 
    $combination[] = $set[$i]; 

    if($length > 1) { 
     $combination = array_merge( 
     $combination, 
     combinations(array_slice($set,1+$i), $length-1) 
    ); 
    } 

    $combinations[] = $combination; 
    } 

    return $combinations; 
} 

$allYourNumbers = range(1,99); 
$allCombinations = combinations($allYourNumbers, 5); 

然後你可以洗牌$ allCombinations和提取物作爲你想要的,但你需要大量的內存和大量的的時間...這樣做可以從來沒有是有效的

1

下面是簡單的代碼,應該運行相當快,做你所描述的。

$numbers = range(1, 99); // numbers to pick from 
$length = 5; // amount of items in the set 
$sets_amount = 15; // amount of sets you want to generate 
shuffle($numbers); // randomize 

function get_set($length, &$numbers) { 
    return array_splice($numbers, 0, $length); 
} 

for ($i = 0; $i < $sets_amount; $i++) 
    print_r(get_set($length, $numbers)); 

注意:它只適用於當你需要幾個組合。你沒有說你想要所有可能的,所以我想如果你只需要一堆他們 - 這是非常快速和簡單的方法來做到這一點。

對於慢一點(您生成越多 - 越慢),但生成任何集的數量,您可以使用此代碼。

$numbers = range(1, 99); // numbers to pick from 
$length = 5; // amount of items in the set 
$sets_amount = 200; // amount of sets you want to generate 
$existing = array(); // where we store existing sets 
$shuffle_period = count($numbers) - $length - 1; // how often we re-randomize the elements 
$j = 0; 

for ($i = 0; $i < $sets_amount; $i++, $j++) { 
    if (!($i % $shuffle_period)) { 
     shuffle($numbers); // randomize at first go and on $shuffle_period 
     $j = 0; 
    } 
    do { 
     $arr = array_slice($numbers, $j, $length); 
    } while (in_array($arr, $existing)); 
    $existing[] = $arr; 
} 

print_r($existing);