使用PHP创建游戏时间表_比我想象的更难

时间:2009-08-04 09:02:04

标签: php arrays multidimensional-array unique permutation

我有一个未知长度的数组,它总是有一个可分的数值,例如:

print_r($initialarray);

Array ( [0] => 30 [1] => 31 [2] => 32 [3] => 33 [4] => 34 [5] => 35 ) 

我需要创建集合:     

Set 1: 30 v 35; 31 v 34; 32 v 33;

Set 2: 30 v 34; 31 v 33; 32 v 35;

Set 3: 30 v 33; 31 v 32; 34 v 35;

Set 4: 30 v 32; 33 v 34; 31 v 35;

Set 5: 30 v 31; 32 v 34; 33 v 35; 

值的顺序除以v表示它们是一组。集合中值的排序无关紧要(我随意地把它放在一起)。正如您所看到的,在任何其他集合或同一集合中都不能存在重复集合。

我尝试了很多不同的东西来提出有用的东西。 我得到的最接近的是将初始值放入包含所有可能有效匹配的级联数组中:

Array ( [0] => Array ( [0] => 35 [1] => 31 ) [1] => Array ( [0] => 34 [1] => 31 ) [2] => Array ( [0] => 33 [1] => 31 ) [3] => Array ( [0] => 32 [1] => 31 ) )

Array ( [0] => Array ( [0] => 35 [1] => 32 ) [1] => Array ( [0] => 34 [1] => 32 ) [2] => Array ( [0] => 33 [1] => 32 ) )

Array ( [0] => Array ( [0] => 35 [1] => 33 ) [1] => Array ( [0] => 34 [1] => 33 ) )

Array ( [0] => Array ( [0] => 35 [1] => 34 ) ) 

这些值是一个名为$ sched的数组中的数组。 我从阵列中留下了30个..哎呀

数字是团队。每支球队都需要为每支球队打一次球。将设置时间表,以便每个团队每周只玩一个游戏。 时间表需要设置几周才能让所有游戏在一周内不超过一次的情况下播放。

我已经使用了排列函数,这就是我想出的上面没有相同匹配的数组。我现在需要弄清楚如何输出时间表,如上面的集合中所示。 (请记住,只要没有球队在同一场比赛中两次比赛,示例所在的顺序无关紧要)

$count = count($initialarray);
$recount = $count -1;
for($u=0; $u < $count;$u++){
    for($d=0;$d<$recount;$d++){
         $vs[$u][$d] = $sched[$d][$u];
    }
$recount -= 1;
}

所以这不起作用,我使它复杂到它应该是的,我不能再围绕这个问题。任何帮助,即使它意味着重新开始,将不胜感激!

5 个答案:

答案 0 :(得分:1)

我没有直接的答案,但看起来你可能需要一点图论。 http://en.wikipedia.org/wiki/Tournament_%28graph_theory%29

答案 1 :(得分:1)

也许这段代码解决了你的问题,它并不像它可能那样优雅,但似乎有效。 你应该知道ho arrangeGames的工作原理;)

也许您需要关注 arrangePlayerforDays 。只有当两个玩家当天没有安排游戏时,它才能在一天内完成各种游戏。 另一个功能只是为了使代码更具可读性(并覆盖 arrangePlayerforDays 中的一对故障)

function gamePrettyPrint($gamesOnADay, $glue) {
  $result=array();
  foreach ($gamesOnADay as $currentGame) 
      $result[]=join($glue,$currentGame);
  return $result;
}

function arrangeGamesOnAday($day) {
  $result=array();
  for ($k=0, $limit=count($day); $k<$limit; $k+=2)
      $result[]=array($day[$k+1], $day[$k]);
  return $result;
}

function arrangeGames($players) { 
  for ($i=0, $limit=count($players); $i < $limit; $i++) 
    for ($j=$i+1; $j<$limit;$j++) 
      $games[]=array($players[$i], $players[$j]);
  return $games;
}

function calculateTournamentDuration($players) {
  return  count($players)-1; // (n!)/(2!*(n-2)!) * (1/n)
}

function arrangePlayerforDays($games, $days) {
  $mem = array_pad(array(),$tournamentDays,array());
  for ($k=0;count($games);$k++)
    if ((array_search($games[0][0],$mem[$k%$days])=== false)  and
        (array_search($games[0][1],$mem[$k%$days])=== false))
      list($mem[$k%$days][], $mem[$k%$days][]) = array_shift($games);
  return ($mem);
}

function scatterGamesOnCalendar($games, $tournamentDays) {
  $days=arrangePlayerforDays($games, $tournamentDays);
  $calendar=array_map('arrangeGamesOnAday',$days);
  return $calendar;
}

//  $initialArray = array('a','b','c','d','e','f','g','h');
$initialArray = array(30,31,32,33,34,35);

$games= arrangeGames($initialArray);
$tournamentSpan = calculateTournamentDuration($initialArray);
$calendar = scatterGamesOnCalendar($games, $tournamentSpan);

while ($day=array_shift($calendar))
  $prettyCalendar[]=gamePrettyPrint($day,' v ');

print_r($prettyCalendar);

答案 2 :(得分:0)

你可以在其中构建一个包含每个“游戏”的数组,所以它就像

0 => 30 v 35
1 => 31 v 34
2 => 32 v 33

这应该很容易。然后你只需要通过这个数组并将游戏放在第一排,其中没有一支球队已经在比赛。可能会有更好更快的解决方案,但这是第一个出现在我脑海中的问题,而且我认为编写它非常简单。

答案 3 :(得分:0)

this问题是否有您想要的答案?

答案 4 :(得分:0)

$team = array( 1 => 30 , 2 => 31 , 3 => 32 , 4 => 33 , 5 => 34 , 6 => 35 );

$numplayers = count($team);
if ($numplayers % 2 != 0) $numplayers++; 
for ($round = 0;$round < $numplayers - 1;$round++) {
    echo 'Set ' . ($round+1) . ":\n\n{$team[1]}-";
    for ($i = 0;$i < $numplayers-1;$i++) {
        if ($i % 2 == 0) {
            $player = ($numplayers-2) - ($i/2) - $round;
        } else {
            $player = ((($i-1)/2) - $round);
        }
        if ($player < 0) $player += $numplayers - 1;
        echo $team[$player+2];
        echo ($i % 2 == 0) ? "\n" : '-';
    }
    echo "\n\n<br/>";
}