随机但唯一的配对,有条件

时间:2011-08-16 21:18:00

标签: php random

我需要一些帮助/方向来设置PHP脚本来随机配对数组中的项目。

  • 每次都应该随机配对这些项目。

  • 这些项目本身不匹配(第1-1项不应与第1-1项配对)

  • 大多数项目都有配偶( item1-1和item1-2)。这些物品不应与其配偶配对。

我一直在玩the second script in this post但是,我无法取得任何进展。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:2)

非常简单的方法,但希望对您有所帮助:

mates ,如果按数组分组(例如数组('a1','a2')),则不会配对。)

function matchUp($array) {
  $result = array();

  while($el = array_pop($array)) {
    shuffle($array);

    if (sizeof($array) > 0) {
      $candidate = array_pop($array);

      $result[] = array(
        array_pop($el),
        array_pop($candidate)
      );

      if (sizeof($el) > 0) {
        $array[] = $el;
      }

      if (sizeof($candidate) > 0) {
        $array[] = $candidate;
      }
    }
    else {
      $result[] = array(array_pop($el));
    }
  }

  return $result;
}

$array = array(
  array('a1', 'a2'),
  array('b1', 'b2'),
  array('c1'),
  array('d1'),
  array('e1', 'e2'),
  array('f1'),
  array('g1', 'g2'),
);

<强>更新

foreach(matchUp($array) as $pair) {
  list($a, $b) = $pair + array(null, null);
  echo '<div style="border: solid 1px #000000;">' . $a . ' + ' . $b . '</div>';
}

答案 1 :(得分:1)

随机性,无法保证将达到完整正确的解决方案。

某些问题集比其他问题更容易解决。有些是不可能的。

您可以配置尝试获得良好解决方案的次数。在指定的尝试次数之后,它将返回它可以找到的最佳解决方案。

function pairUp (array $subjectArray) {
    // Config options
    $tries = 50;

    // Variables
    $bestPaired = array();
    $bestUnpaired = array();

    for($try = 1; $try <= 50; $try++) {
        $paired = array();
        $unpaired = array();
        $toBePaired = $subjectArray;

        foreach($subjectArray as $subjectIndex => $subjectValue) {
            // Create array without $thisValue anywhere, from the unpaired items
            $cleanArray = array();
            foreach($toBePaired as $index => $value) {
                if($value != $subjectValue) {
                    array_push($cleanArray, array(
                        'index' => $index,
                        'value' => $value
                    ));
                }
            }
            sort($cleanArray); // reset indexes in array

            // See if we have any different values left to match
            if(count($cleanArray) == 0) {
                array_push($unpaired, $subjectValue);
                continue;
            }

            // Get a random item from the clean array
            $randomIndex = rand(0,count($cleanArray)-1);
            // Store this pair
            $paired[$subjectIndex] = $subjectValue . '-' . $cleanArray[$randomIndex]['value'];
            // This item has been paired, remove it from unpairedItems
            unset($toBePaired[$cleanArray[$randomIndex]['index']]);
            sort($toBePaired);
        }

        // Decide if this is our best try
        if(count($paired) > count($bestPaired)) {
            $bestPaired = $paired;
            $bestUnpaired = $unpaired;
        }

        // If we had no failures, this was a perfect try - finish
        if(count($unpaired) == 0) { $break; }
    }

    // We're done, send our array of pairs back.
    return array(
        'paired' => $bestPaired,
        'unpaired' => $bestUnpaired
    );
}

var_dump(pairUp(array('a','b','c','d','e','a','b','c','d','e')));
/*
Example output:
array(2) {
  ["paired"]=>
  array(10) {
    [0]=>
    string(3) "a-b"
    [1]=>
    string(3) "b-c"
    [2]=>
    string(3) "c-d"
    [3]=>
    string(3) "d-e"
    [4]=>
    string(3) "e-a"
    [5]=>
    string(3) "a-b"
    [6]=>
    string(3) "b-e"
    [7]=>
    string(3) "c-d"
    [8]=>
    string(3) "d-c"
    [9]=>
    string(3) "e-a"
  }
  ["unpaired"]=>
  array(0) {
  }
}
*/

答案 2 :(得分:1)

案例1:如果所有元素都有配偶

如果所有元素都有配对,则以下解决方案可行,但我不知道它是否完全随机(如所有可能的输出具有相同的概率):

  1. 随机播放元素列表,保持配偶

     original list = (a1,a2),(b1,b2),(c1,c2),(d1,d2)
     shuffled      = (c1,c2),(d1,d2),(a1,a2),(b1,b2)
    
  2. 将第二个配合向右移动。比赛已经形成。

     shifted       = (c1,b2),(d1,c2),(a1,d2),(b1,a2)
    
  3. (编辑1:如果完全按照描述应用,则a1无法与b1匹配。因此,在转移之前,您可能想要为每对配偶投掷一枚硬币来决定他们是否应该改变秩序。)

    案例2:如果只有一些元素有配偶

    因为在你的问题中只有一些元素会有配偶,我想有人可以提出以下内容:

    1. 任意配对那些没有配偶的元素。应该有偶数个这样的元素。否则,元素的总数将是奇数,因此首先不能进行匹配。

      original list = (a1,a2),(b1,b2),c1,d1,e1,f1  // c1,d1,e1 and f1 don't have mates
      list2         = (a1,a2),(b1,b2),(c1,d1),(e1,f1) // pair them up 
      
    2. 如案例1中那样随机移动以形成匹配。

      shuffled = (e1,f1),(a1,a2),(c1,d1),(b1,b2) 
      shifted  = (e1,b2),(a1,f1),(c1,a2),(b1,d1) 
      
    3. 同样,我不知道这是否完全随机,但我认为它应该有用。

      (编辑2:简化解决方案)

      (编辑3:如果元素的总数是奇数,有人将没有匹配,所以在开头随机选择一个元素将其遗漏,然后应用上面的算法。)