Создание игрового расписания с PHP _ Сложнее, чем я думал - PullRequest
3 голосов
/ 04 августа 2009

У меня есть массив неизвестной длины , который всегда будет иметь равномерно делимое количество значений, например:

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 ]

1 голос
/ 04 августа 2009

У меня нет прямого ответа, но, похоже, вам может понадобиться немного теории графов. http://en.wikipedia.org/wiki/Tournament_%28graph_theory%29

1 голос
/ 04 августа 2009

Возможно, этот код решит вашу проблему, он не так элегантен, как мог бы, но, кажется, работает. Вы должны знать, как устроены игры;)

Может быть, вам нужно обратить внимание на rangePlayerforDays . Это ставит различные игры в один день, только если у обоих игроков не запланирована игра на этот день. Другая функция только для того, чтобы сделать код более читабельным (и покрыть пару глюков в rangePlayerforDays )

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);
0 голосов
/ 04 декабря 2010
$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/>";
}
0 голосов
/ 06 августа 2009

Имеет ли этот вопрос ответ на ваш вопрос?

0 голосов
/ 04 августа 2009

Вы можете построить массив с каждой "игрой", чтобы он был похож на

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

Это должно быть довольно легко. Затем вы просто просматриваете этот массив и помещаете игру в первый ряд, где ни одна из команд уже не играет. Возможно, есть лучшие и более быстрые решения, но это первое, что пришло мне в голову, и я думаю, что написать его довольно просто.

...