动态获取/排序下一个多维数组元素

时间:2017-02-15 01:28:04

标签: php arrays multidimensional-array

我目前正在经历一个伟大的老脑屁并且动态地选择下一轮的获胜者将进行的下一轮“轮次比赛”:

generated ladder

上面的梯子是动态生成的,我想要做的就是找出下一个匹配ID。我目前已将此作为POC,但如果竞争阶梯达到64 /更多,则不可持续:

$ar = [
 1 => [
     ['id' => 1,'name' => 'round1, pair 1'],
     ['id' => 2,'name' => 'round1, pair 2'],
     ['id' => 3,'name' => 'round1, pair 3'],
     ['id' => 4,'name' => 'round1, pair 4'],
 ],
 2 => [
     ['id' => 5,'name' => 'round2, pair 1'],
     ['id' => 6,'name' => 'round2, pair 2'],
 ]
];

$cases = [0, 0, 1, 1, 2, 2];

foreach($ar as $i => $round) {

    foreach($round as $_i => $r) {
        echo $r['name'] . " & NEXT_MATCH_ID::> " . $ar[($i + 1)][$cases[$_i]]['id'] . "<br /> ";
    }
}

例如,是否有更简化的方法可以实现上述没有硬编码变量( $cases )的内容。

基本上,“匹配/对”的数量将减半,因为梯形图将是:4 - &gt; 2 - &gt; 1

上面会生成正确的ID,但它不可扩展或动态;

round1, pair 1 & NEXT_MATCH_ID::> 5
round1, pair 2 & NEXT_MATCH_ID::> 5
round1, pair 3 & NEXT_MATCH_ID::> 6
round1, pair 4 & NEXT_MATCH_ID::> 6
round2, pair 1 & NEXT_MATCH_ID::> ...
round2, pair 2 & NEXT_MATCH_ID::> ...
//......etc etc...

Demo/ Example上述代码(如果需要)。

备注

  • “球员/球队”比赛没有限制,这可以是指数级的,4, 6, 8, 10, 12, 14, 16, 18....32, 34...64...etc
  • 这将永远不会发生/适用于上一轮(总决赛 - 1比赛),因为没有进一步的进展。 (很容易受if($i == count($rounds)) {.... do not continue... 限制。)
  • 有可能同时运行多个匹配,因此“下一轮ID”可以lastId + 1

1 个答案:

答案 0 :(得分:1)

只是数学

请注意,每一轮都包含pow(2, Rounds - Round + 1)个团队和pow(2, Rounds - Round)个匹配项。把它总结为几何级数。

$round之前进行的匹配数是geometric progression 2^(rounds-1) + 2^(rounds-2) + ... 2^(rounds - round + 1)a=2^(rounds-1)r=1/2n=round-1。它的总和是2^(rounds) - 2^(rounds+1-round)

所以匹配ID和下一个匹配ID只是三个参数的函数:pairnumroundrounds。我将其计算结果转换为函数getMatchIdgetNextId

示例

<?php
// just matchesInPreviousRounds + parnum
function getMatchId($pairnum, $round, $rounds) {
    // matchesInPreviousRounds - is a sum of a geometric progression  
    // 2^(rounds-1) + 2^(rounds-2) + ... 2^(rounds - round + 1) 
    // with a=2^(rounds-1), r=1/2, n = round-1
    // its sum is 2^(rounds) - 2^(rounds+1-round)
    $inPreviousRounds = $round > 1 ?  (pow(2, $rounds) - pow(2, $rounds + 1 - $round)) : 0;

    $id = $inPreviousRounds + $pairnum;

    return (int)$id;
}

// next id is last id of a round + half a pairnum.
function getNextId($pairnum, $round, $rounds) {
    if($round === $rounds) {
        return false;
    }

    $matchesInThisAndPreviousRounds = pow(2, $rounds) - pow(2, $rounds - $round);

    $nextid = $matchesInThisAndPreviousRounds + ceil($pairnum / 2);

    return (int)$nextid;
}

$divide = 64; // for 1/64 at the start
$power = round(log($divide) / log(2)); // get 6 for 64
$rounds = (int) $power + 1;


for($round = 1; $round <= $rounds; $round++) {
    // every round contains 2^($rounds - $round + 1) of teams 
    // and has 2^($rounds - $round) of matches
    $teamsLeft = pow(2, $rounds - $round + 1);
    $pairsLeft = pow(2, $rounds - $round);


    for($pairnum = 1; $pairnum <= $pairsLeft; $pairnum++) {
        $id = getMatchId($pairnum, $round, $rounds);
        $nextid = getNextId($pairnum, $round, $rounds);

        echo "Round $round, pair $pairnum, id $id ";
        echo "winner goes to " . $nextid ? $nextid : "A BAR" . "\n";
    }
}

其结果

Round 1, pair 1, id 1, winner goes to 65
Round 1, pair 2, id 2, winner goes to 65
...
Round 1, pair 62, id 62, winner goes to 95
Round 1, pair 63, id 63, winner goes to 96
Round 1, pair 64, id 64, winner goes to 96
Round 2, pair 1, id 65, winner goes to 97
Round 2, pair 2, id 66, winner goes to 97
...
Round 2, pair 29, id 93, winner goes to 111
Round 2, pair 30, id 94, winner goes to 111
Round 2, pair 31, id 95, winner goes to 112
Round 2, pair 32, id 96, winner goes to 112
Round 3, pair 1, id 97, winner goes to 113
Round 3, pair 2, id 98, winner goes to 113
...
Round 3, pair 13, id 109, winner goes to 119
Round 3, pair 14, id 110, winner goes to 119
Round 3, pair 15, id 111, winner goes to 120
Round 3, pair 16, id 112, winner goes to 120
Round 4, pair 1, id 113, winner goes to 121
Round 4, pair 2, id 114, winner goes to 121
...
Round 4, pair 7, id 119, winner goes to 124
Round 4, pair 8, id 120, winner goes to 124
Round 5, pair 1, id 121, winner goes to 125
Round 5, pair 2, id 122, winner goes to 125
Round 5, pair 3, id 123, winner goes to 126
Round 5, pair 4, id 124, winner goes to 126
Round 6, pair 1, id 125, winner goes to 127
Round 6, pair 2, id 126, winner goes to 127
Round 7, pair 1, id 127, winner goes to A BAR