将循环赛 1v1 扩展为 1v1v1v1
Expanding Round-robin tournament 1v1 to a 1v1v1v1
我正在尝试将循环算法从 1v1 组扩展和改进为 1v1v1v1 组(类似于所有人免费)。我已经制定了功能本身来执行时间表,但是当我尝试扩展它时,一些团队重复了。例如,我有 16 支球队,我想进行 5 轮比赛,球队 1 在 5 轮比赛中出现 7 次,球队 2 在 5 轮比赛中出现 3 次。我需要他们在 most.I 出现 5 次,真的不明白我该怎么做。欢迎任何建议和链接。
function make_schedule(array $teams, int $rounds = null, bool $shuffle = true, int $seed = null): array
{
$teamCount = count($teams);
if($teamCount < 4) {
return [];
}
//Account for odd number of teams by adding a bye
if($teamCount % 2 === 1) {
array_push($teams, null);
$teamCount += 1;
}
if($shuffle) {
//Seed shuffle with random_int for better randomness if seed is null
srand($seed ?? random_int(PHP_INT_MIN, PHP_INT_MAX));
shuffle($teams);
} elseif(!is_null($seed)) {
//Generate friendly notice that seed is set but shuffle is set to false
trigger_error('Seed parameter has no effect when shuffle parameter is set to false');
}
$quadTeamCount = $teamCount / 4;
if($rounds === null) {
$rounds = $teamCount - 1;
}
$schedule = [];
for($round = 1; $round <= $rounds; $round += 1) {
$matchupPrev = null;
foreach($teams as $key => $team) {
if($key >= $quadTeamCount ) {
break;
}
$keyCount = $key + $quadTeamCount;
$keyCount2 = $key + $quadTeamCount + 1;
$keyCount3 = $key + $quadTeamCount + 2;
$team1 = $team;
$team2 = $teams[$keyCount];
$team3 = $teams[$keyCount2];
$team4 = $teams[$keyCount3];
//echo "<pre>Round #{$round}: {$team1} - {$team2} - {$team3} - {$team4} == KeyCount: {$keyCount} == KeyCount2: {$keyCount2} == KeyCount3: {$keyCount3}</pre>";
//Home-away swapping
$matchup = $round % 2 === 0 ? [$team1, $team2, $team3, $team4 ] : [$team2, $team1, $team4, $team3];
$schedule[$round][] = $matchup ;
}
rotate($teams);
}
return $schedule;
}
旋转功能:
function rotate(array &$items)
{
$itemCount = count($items);
if($itemCount < 3) {
return;
}
$lastIndex = $itemCount - 1;
/**
* Though not technically part of the round-robin algorithm, odd-even
* factor differentiation included to have intuitive behavior for arrays
* with an odd number of elements
*/
$factor = (int) ($itemCount % 2 === 0 ? $itemCount / 2 : ($itemCount / 2) + 1);
$topRightIndex = $factor - 1;
$topRightItem = $items[$topRightIndex];
$bottomLeftIndex = $factor;
$bottomLeftItem = $items[$bottomLeftIndex];
for($i = $topRightIndex; $i > 0; $i -= 1) {
$items[$i] = $items[$i - 1];
}
for($i = $bottomLeftIndex; $i < $lastIndex; $i += 1) {
$items[$i] = $items[$i + 1];
}
$items[1] = $bottomLeftItem;
$items[$lastIndex] = $topRightItem;
}
例如:
如果我将轮数设置为 5,则每支球队进行 5 场比赛。
Array example Screenshot
处理第5轮:
好吧,我想了一下,也许没有办法让他们不重复地玩,但是如果把它降低到最低限度,比如每支球队应该只玩 5 次——这意味着一轮.我正是这个意思。我在 'they repeat' 下的意思是:16 支球队,5 轮,有些球队在所有这些轮中进行了 7 次,而其他球队在这 5 轮中进行了 3 次。我想避免这种情况,让每支球队最多打5轮。
你的 foreach()
与其他 3 个团队的 selection 是错误的。其中之一必须以 4
的倍数进行步数。如果不这样做,您将 select 开头的团队多于一个,而根本不会 select 数组末尾的团队。这将导致像这样的错误团队对决(这里的团队是字母):
abcd
bcde
cdef
defg
然后你的 break;
成功了。
相反,它应该看起来像这样:
for ($i=0; $i<4; $i++) {
$matchup = array();
for ($j=0; $j<4; $j++) {
$matchup[] = $teams[4*$i+$j];
}
$schedule[$round][] = $matchup ;
}
这样你就得到了以下配对(同样,使用字母作为团队):
abcd
efgh
ijkl
mnop
此算法会将团队列表分成四组:
abcd|efgh|ijkl|mnop
请记住,根据下一轮 $teams
数组的洗牌,您可能会遇到同一个对手两次。
adei|klnf|gjmc|pobh
这里 ad
、kl
和 op
队将再次相遇。
我正在尝试将循环算法从 1v1 组扩展和改进为 1v1v1v1 组(类似于所有人免费)。我已经制定了功能本身来执行时间表,但是当我尝试扩展它时,一些团队重复了。例如,我有 16 支球队,我想进行 5 轮比赛,球队 1 在 5 轮比赛中出现 7 次,球队 2 在 5 轮比赛中出现 3 次。我需要他们在 most.I 出现 5 次,真的不明白我该怎么做。欢迎任何建议和链接。
function make_schedule(array $teams, int $rounds = null, bool $shuffle = true, int $seed = null): array
{
$teamCount = count($teams);
if($teamCount < 4) {
return [];
}
//Account for odd number of teams by adding a bye
if($teamCount % 2 === 1) {
array_push($teams, null);
$teamCount += 1;
}
if($shuffle) {
//Seed shuffle with random_int for better randomness if seed is null
srand($seed ?? random_int(PHP_INT_MIN, PHP_INT_MAX));
shuffle($teams);
} elseif(!is_null($seed)) {
//Generate friendly notice that seed is set but shuffle is set to false
trigger_error('Seed parameter has no effect when shuffle parameter is set to false');
}
$quadTeamCount = $teamCount / 4;
if($rounds === null) {
$rounds = $teamCount - 1;
}
$schedule = [];
for($round = 1; $round <= $rounds; $round += 1) {
$matchupPrev = null;
foreach($teams as $key => $team) {
if($key >= $quadTeamCount ) {
break;
}
$keyCount = $key + $quadTeamCount;
$keyCount2 = $key + $quadTeamCount + 1;
$keyCount3 = $key + $quadTeamCount + 2;
$team1 = $team;
$team2 = $teams[$keyCount];
$team3 = $teams[$keyCount2];
$team4 = $teams[$keyCount3];
//echo "<pre>Round #{$round}: {$team1} - {$team2} - {$team3} - {$team4} == KeyCount: {$keyCount} == KeyCount2: {$keyCount2} == KeyCount3: {$keyCount3}</pre>";
//Home-away swapping
$matchup = $round % 2 === 0 ? [$team1, $team2, $team3, $team4 ] : [$team2, $team1, $team4, $team3];
$schedule[$round][] = $matchup ;
}
rotate($teams);
}
return $schedule;
}
旋转功能:
function rotate(array &$items)
{
$itemCount = count($items);
if($itemCount < 3) {
return;
}
$lastIndex = $itemCount - 1;
/**
* Though not technically part of the round-robin algorithm, odd-even
* factor differentiation included to have intuitive behavior for arrays
* with an odd number of elements
*/
$factor = (int) ($itemCount % 2 === 0 ? $itemCount / 2 : ($itemCount / 2) + 1);
$topRightIndex = $factor - 1;
$topRightItem = $items[$topRightIndex];
$bottomLeftIndex = $factor;
$bottomLeftItem = $items[$bottomLeftIndex];
for($i = $topRightIndex; $i > 0; $i -= 1) {
$items[$i] = $items[$i - 1];
}
for($i = $bottomLeftIndex; $i < $lastIndex; $i += 1) {
$items[$i] = $items[$i + 1];
}
$items[1] = $bottomLeftItem;
$items[$lastIndex] = $topRightItem;
}
例如:
如果我将轮数设置为 5,则每支球队进行 5 场比赛。 Array example Screenshot
处理第5轮:
好吧,我想了一下,也许没有办法让他们不重复地玩,但是如果把它降低到最低限度,比如每支球队应该只玩 5 次——这意味着一轮.我正是这个意思。我在 'they repeat' 下的意思是:16 支球队,5 轮,有些球队在所有这些轮中进行了 7 次,而其他球队在这 5 轮中进行了 3 次。我想避免这种情况,让每支球队最多打5轮。
你的 foreach()
与其他 3 个团队的 selection 是错误的。其中之一必须以 4
的倍数进行步数。如果不这样做,您将 select 开头的团队多于一个,而根本不会 select 数组末尾的团队。这将导致像这样的错误团队对决(这里的团队是字母):
abcd
bcde
cdef
defg
然后你的 break;
成功了。
相反,它应该看起来像这样:
for ($i=0; $i<4; $i++) {
$matchup = array();
for ($j=0; $j<4; $j++) {
$matchup[] = $teams[4*$i+$j];
}
$schedule[$round][] = $matchup ;
}
这样你就得到了以下配对(同样,使用字母作为团队):
abcd
efgh
ijkl
mnop
此算法会将团队列表分成四组:
abcd|efgh|ijkl|mnop
请记住,根据下一轮 $teams
数组的洗牌,您可能会遇到同一个对手两次。
adei|klnf|gjmc|pobh
这里 ad
、kl
和 op
队将再次相遇。