Algorithm 锦标赛括号放置算法
给定一个对手种子列表(例如种子1到16),我正在尝试编写一个算法,该算法将导致在该轮中顶部种子扮演最低种子,第二个种子扮演第二个最低种子,等等 将1号和16号、2号和15号等分为“比赛”是相当容易的,但我还需要确保较高的种子将在随后的几轮中扮演较低的种子 放置正确的支架示例: 1 vs 16 1 vs 8 8 vs 9 1 vs 4 4 vs 13 4 vs 5 5 vs 12 1 vs 2 2 vs 15 2 vs 7 7 vs 10 2 vs 3 3 vs 14 3 vs 6 6 vs 11 1比16 1比8 8比9 1对4 4比13 4比5 5比12 1对2 2比15 2对7 7比10 2对3 3比14 3比6 6比11 正如你所见,种子1和种子2只在决赛中相遇。Algorithm 锦标赛括号放置算法,algorithm,language-agnostic,brackets,tournament,Algorithm,Language Agnostic,Brackets,Tournament,给定一个对手种子列表(例如种子1到16),我正在尝试编写一个算法,该算法将导致在该轮中顶部种子扮演最低种子,第二个种子扮演第二个最低种子,等等 将1号和16号、2号和15号等分为“比赛”是相当容易的,但我还需要确保较高的种子将在随后的几轮中扮演较低的种子 放置正确的支架示例: 1 vs 16 1 vs 8 8 vs 9 1 vs 4 4 vs 13 4 vs 5 5 vs 12
- 在每一轮中,根据播种标准对团队进行排序
- (如果一轮有n个队)第i个位置的队与n-i+1队比赛
{1,2} --- create next layer
{1, _}
/ --- now fill the empty slots
{1,2}
\{2, _}
{1, 4} --- the slots filled in reverse order
/
{1,2}
\{2, 3} --- create next layer again
/{1, _}
{1, 4}
/ \{4, _}
{1,2} --- again fill
\ /{2, _}
{2, 3}
\{3, _}
/{1, 8}
{1, 4}
/ \{4, 5} --- ... and so on
{1,2}
\ /{2, 7}
{2, 3}
\{3, 6}
如您所见,它生成的树与您发布的树相同。我提出了以下算法。它可能不是超高效的,但我不认为它真的需要。它是用PHP编写的
此JavaScript返回一个数组,其中每个偶数索引播放下一个奇数索引
function seeding(numPlayers){
var rounds = Math.log(numPlayers)/Math.log(2)-1;
var pls = [1,2];
for(var i=0;i<rounds;i++){
pls = nextLayer(pls);
}
return pls;
function nextLayer(pls){
var out=[];
var length = pls.length*2+1;
pls.forEach(function(d){
out.push(d);
out.push(length-d);
});
return out;
}
}
> seeding(2)
[1, 2]
> seeding(4)
[1, 4, 2, 3]
> seeding(8)
[1, 8, 4, 5, 2, 7, 3, 6]
> seeding(16)
[1, 16, 8, 9, 4, 13, 5, 12, 2, 15, 7, 10, 3, 14, 6, 11]
函数种子设定(numPlayers){
var rounds=Math.log(numPlayers)/Math.log(2)-1;
var-pls=[1,2];
对于(var i=0;i)(2)
[1, 2]
>播种(4)
[1, 4, 2, 3]
>播种(8)
[1, 8, 4, 5, 2, 7, 3, 6]
>播种(16)
[1, 16, 8, 9, 4, 13, 5, 12, 2, 15, 7, 10, 3, 14, 6, 11]
#python中有一个-它使用嵌套列表理解来简洁:
从数学导入日志,ceil
def种子(n):
“”“以标准比赛种子顺序返回n的列表
请注意,n不必是2的幂-“是”返回为零
"""
ol=[1]
对于范围内的i(cel(log(n)/log(2)):
l=2*len(ol)+1
ol=[e if e由于在搜索主题时会出现这种情况,并且无法找到解决问题的另一个答案,并且无法将种子按“更漂亮”的顺序排列,因此我将添加darkangel提供的PHP代码版本。我还添加了向更高种子玩家表示“是”的可能性
这是在OO环境中编写的,因此参与者的数量在$This->finalinters中,通过的数量在$This->yes中。我只测试了没有通过和两个通过的代码
public function getBracket() {
$players = range(1, $this->finalists);
for ($i = 0; $i < log($this->finalists / 2, 2); $i++) {
$out = array();
$reverse = false;
foreach ($players as $player) {
$splice = pow(2, $i);
if ($reverse) {
$out = array_merge($out, array_splice($players, -$splice));
$out = array_merge($out, array_splice($players, 0, $splice));
$reverse = false;
} else {
$out = array_merge($out, array_splice($players, 0, $splice));
$out = array_merge($out, array_splice($players, -$splice));
$reverse = true;
}
}
$players = $out;
}
if ($this->byes) {
for ($i = 0; $i < $this->byes; $i++ ) {
for ($j = (($this->finalists / pow(2, $i)) - 1); $j > 0; $j--) {
$newPlace = ($this->finalists / pow(2, $i)) - 1;
if ($players[$j] > ($this->finalists / (pow(2 ,($i + 1))))) {
$player = $players[$j];
unset($players[$j]);
array_splice($players, $newPlace, 0, $player);
}
}
}
for ($i = 0; $i < $this->finalists / (pow(2, $this->byes)); $i++ ) {
$swap[] = $players[$i];
}
for ($i = 0; $i < $this->finalists /(pow(2, $this->byes)); $i++ ) {
$players[$i] = $swap[count($swap) - 1 - $i];
}
return array_reverse($players);
}
return $players;
}
公共函数getBracket(){
$players=范围(1,$this->决赛选手);
对于($i=0;$ifinalists/2,2);$i++){
$out=array();
$reverse=false;
foreach($player作为$player){
$splice=pow(2$i);
如果($反向){
$out=阵列合并($out,阵列拼接($players,$splice));
$out=阵列合并($out,阵列拼接($players,0,$splice));
$reverse=false;
}否则{
$out=阵列合并($out,阵列拼接($players,0,$splice));
$out=阵列合并($out,阵列拼接($players,$splice));
$reverse=true;
}
}
$players=$out;
}
如果($this->yes){
对于($i=0;$i<$this->yes;$i++){
对于($j=($this->决赛选手/pow(2$i))-1);$j>0;$j--){
$newPlace=($this->决赛选手/pow(2$i))-1;
如果($players[$j]>($this->入围者/(pow(2,($i+1‘‘‘)')){
$player=$players[$j];
未设置($players[$j]);
阵列拼接($players,$newPlace,0,$player);
}
}
}
对于($i=0;$i<$this->入围者/(pow(2,$this->是));$i++){
$swap[]=$players[$i];
}
对于($i=0;$i<$this->入围者/(pow(2,$this->是));$i++){
$players[$i]=$swap[计数($swap)-1-$i];
}
返回数组\u反向($players);
}
返回$players;
}
对于JavaScript代码,请使用以下两个函数之一。前者体现命令式风格,速度更快。后者是递归的,更简洁,但只适用于相对较少的团队(>1,m=1;i>=1;i>=1,m=(m 0;j-=i){
arr[j]=m-arr[j-=i]
}
}
返回arr
}
在这里,您可以通过镜像已占用的位置来逐个填充这些位置。例如,第一个种子团队(即编号为0
)位于最顶端的位置。第二个团队(1
)位于括号另一半的相对位置。第三个团队(2
)将1
镜像到括号的一半,依此类推。尽管存在嵌套循环,但该算法的时间复杂度取决于团队的数量
以下是递归方法:
//函数式样式
常量foo=n=>
n===1?[0]:foo(n>>1).reduce((p,c)=>[…p,c,n-c-1],)
基本上,您可以执行与上一个函数相同的镜像,但会以递归方式执行:
- 对于
团队,它只是n=1
[0]
- 对于
团队,将此函数应用于参数n=2
(即,n-1
)&get1
。然后通过插入镜像 元素[0]
public function getBracket() { $players = range(1, $this->finalists); for ($i = 0; $i < log($this->finalists / 2, 2); $i++) { $out = array(); $reverse = false; foreach ($players as $player) { $splice = pow(2, $i); if ($reverse) { $out = array_merge($out, array_splice($players, -$splice)); $out = array_merge($out, array_splice($players, 0, $splice)); $reverse = false; } else { $out = array_merge($out, array_splice($players, 0, $splice)); $out = array_merge($out, array_splice($players, -$splice)); $reverse = true; } } $players = $out; } if ($this->byes) { for ($i = 0; $i < $this->byes; $i++ ) { for ($j = (($this->finalists / pow(2, $i)) - 1); $j > 0; $j--) { $newPlace = ($this->finalists / pow(2, $i)) - 1; if ($players[$j] > ($this->finalists / (pow(2 ,($i + 1))))) { $player = $players[$j]; unset($players[$j]); array_splice($players, $newPlace, 0, $player); } } } for ($i = 0; $i < $this->finalists / (pow(2, $this->byes)); $i++ ) { $swap[] = $players[$i]; } for ($i = 0; $i < $this->finalists /(pow(2, $this->byes)); $i++ ) { $players[$i] = $swap[count($swap) - 1 - $i]; } return array_reverse($players); } return $players; }
<?php define('NUMBER_OF_PARTICIPANTS', 16); $participants = range(1,NUMBER_OF_PARTICIPANTS); $bracket = getBracket($participants); var_dump($bracket); function getBracket($participants) { $participantsCount = count($participants); $rounds = ceil(log($participantsCount)/log(2)); $bracketSize = pow(2, $rounds); $requiredByes = $bracketSize - $participantsCount; echo sprintf('Number of participants: %d<br/>%s', $participantsCount, PHP_EOL); echo sprintf('Number of rounds: %d<br/>%s', $rounds, PHP_EOL); echo sprintf('Bracket size: %d<br/>%s', $bracketSize, PHP_EOL); echo sprintf('Required number of byes: %d<br/>%s', $requiredByes, PHP_EOL); if($participantsCount < 2) { return array(); } $matches = array(array(1,2)); for($round=1; $round < $rounds; $round++) { $roundMatches = array(); $sum = pow(2, $round + 1) + 1; foreach($matches as $match) { $home = changeIntoBye($match[0], $participantsCount); $away = changeIntoBye($sum - $match[0], $participantsCount); $roundMatches[] = array($home, $away); $home = changeIntoBye($sum - $match[1], $participantsCount); $away = changeIntoBye($match[1], $participantsCount); $roundMatches[] = array($home, $away); } $matches = $roundMatches; } return $matches; } function changeIntoBye($seed, $participantsCount) { //return $seed <= $participantsCount ? $seed : sprintf('%d (= bye)', $seed); return $seed <= $participantsCount ? $seed : null; } ?>
Number of participants: 16 Number of rounds: 4 Bracket size: 16 Required number of byes: 0 C:\projects\draw\draw.php:7: array (size=8) 0 => array (size=2) 0 => int 1 1 => int 16 1 => array (size=2) 0 => int 9 1 => int 8 2 => array (size=2) 0 => int 5 1 => int 12 3 => array (size=2) 0 => int 13 1 => int 4 4 => array (size=2) 0 => int 3 1 => int 14 5 => array (size=2) 0 => int 11 1 => int 6 6 => array (size=2) 0 => int 7 1 => int 10 7 => array (size=2) 0 => int 15 1 => int 2
Number of participants: 6 Number of rounds: 3 Bracket size: 8 Required number of byes: 2 C:\projects\draw\draw.php:7: array (size=4) 0 => array (size=2) 0 => int 1 1 => null 1 => array (size=2) 0 => int 5 1 => int 4 2 => array (size=2) 0 => int 3 1 => int 6 3 => array (size=2) 0 => null 1 => int 2
int * pctournamentSeedArray(int PlayerCnt) { int * Array; int * PrevArray; int i; Array = meAlloc(sizeof(int) * PlayerCnt); if (PlayerCnt == 2) { Array[0] = 0; Array[1] = 1; return Array; } PrevArray = pctournamentSeedArray(PlayerCnt / 2); for (i = 0; i < PlayerCnt;i += 2) { Array[i] = PrevArray[i / 2]; Array[i + 1] = (PlayerCnt - 1) - Array[i] ; } meFree(PrevArray); return Array; }