首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >迭代(循环)复杂的数字范围,使用组生成括号表

迭代(循环)复杂的数字范围,使用组生成括号表
EN

Stack Overflow用户
提问于 2013-09-01 15:28:35
回答 3查看 684关注 0票数 4

我正在尝试建立一个处理比赛托架表的算法。我要查一下一系列的数字。每个数字都有运动员的名字。数字是随机分配给运动员的,但是数字的配对必须始终保持不变。有两组奇数和偶数,即A和B。

唯一的问题是我无法找到适当的算法来迭代数字,确切的方式是,如下所示:

代码语言:javascript
复制
Group A:
--------
  1
  17

  9
  25
------
  5
  21

  13
  29
------
  3
  19

  11
  27
------                         
  7
  23

  15
  31


Group B:
--------
  2
  18

  10
  26
------                          
  6
  22

  14
  30
------   
  4
  20

  12
  28
------
  8
  24

  16
  32

有谁能帮我提一下建议,或者举例说明如何获得上面的输出?

编辑1:

上面的例子是32名运动员的托架表!如果您对4、8、16、64或128名运动员使用工作表,则必须应用相同的逻辑!

编辑2:

让我们用4名运动员的工作表和16名运动员的工作表更清楚地说明。

4名运动员的表:

代码语言:javascript
复制
Group A:
--------
  1
  3

Group B:
--------
  2
  4

16名运动员名单:

代码语言:javascript
复制
Group A:
--------
  1
  9

  5
  13
------
  3
  11

  7
  15

Group B:
--------
  2
  10

  6
  14
------                              
  4
  12

  8
  16

编辑3:

最后一部分,我计划有一个列有运动员的名字和它在其中的地位。我所说的状态是指,如果运动员以前是冠军(强者),那么他/她的状态是1,如果运动员以前的成绩不为人所知,或者是最小的(弱的),那么他/她的状态就是。这样我们就可以把最强壮的运动员分成不同的小组,确保他们不会在第一场比赛中互相对抗,而是更接近半决赛或决赛。

数组示例:

代码语言:javascript
复制
$participants = array(
array("John", 0),
array("Gagan", 0),
array("Mike Tyson", 1),
array("Gair", 0),
array("Gale", 0),
array("Roy Johnes", 1),
array("Galip", 0),
array("Gallagher", 0),
array("Garett", 0),
array("Nikolai Valuev", 1),
array("Garner", 0),
array("Gary", 0),
array("Gelar", 0),
array("Gershom", 0),
array("Gilby", 0),
array("Gilford", 0)
);

从这个例子我们可以看出,具有1级的运动员必须属于不同的组,即A组和B组,但我们只有两组数值奇数和偶数,在这个例子中,有3名强运动员。因此,他们中的两人将属于同一组。最终的结果必须是,这两名在同一组中的强壮运动员,在第一场比赛中就不能见面(这意味着他们不会在同一对号码上,并且尽可能地远离对方,这样他们就不会在第二场比赛中相遇)。

然后,随机地,我计划重新排列这个数组,并将运动员发送到括号表上--每次都有不同的数字--,每一次都有不同的数字--,那些有国旗的 1 的运动员,去不同的组,或者每次在第一次比赛的上,运动员的名字都分配给同一个号码。E 221

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-09-03 11:05:47

好的,我终于把我的Tcl代码转换成PHP了!我也改变了一些事情:

代码语言:javascript
复制
<?php

// Function generating order participants will be placed in array
function getBracket($L) {
    // List will hold insert sequence
    $list = array();
    // Bracket will hold final order of participants
    $bracket = array();
    // The algorithm to generate the insert sequence
    for ($n = 1; $n <= $L; $n += 1) {
        // If 'perfect' number, just put it (Perfect no.s: 2, 4, 8, 16, 32, etc)
        if (substr(log($n)/log(2), -2) == ".0") {
            $list[] = $n;
        // If odd number, stuff...
        } elseif ($n % 2 == 1) {
            $list[] = $list[($n-1)/2];
        // Else even number, stuff...
        } else {
            $list[] = $list[$n/2-1]+$n/2;
        }
    }

    // Insert participant order as per insert sequence
    for ($i = 1; $i <= sizeof($list); $i += 1) {
        $id = $i-1;
        array_splice($bracket, $list[$id], 0, $i);
    }
    return $bracket;
}

// Find number of participants over 'perfect' number if any
function cleanList($L) {
    for ($d = 1; $L > $d; $d += 1) {
        $sq = $L-pow(2,$d);
        if($sq == 0) {break;}
        if($sq < 0) {
            $d = pow(2,$d-1);
            $diff = $L-$d;
            break;
        }
    }
    return $diff;
}

$participants = array(
    array(0, "John", 2),
    array(1, "Gagan", 1),
    array(2, "Mike Tyson", 1),
    array(3, "Gair", 1),
    array(4, "Gale", 0),
    array(5, "Roy Johnes", 0),
    array(6, "Galip", 0),
    array(7, "Gallagher", 0),
    array(8, "Garett", 0),
    array(9, "Nikolai Valuev", 0),
    array(10, "Garner", 1),
    array(11, "Gary", 0),
    array(12, "Gelar", 0),
    array(13, "Gershom", 1),
    array(14, "Gilby", 0),
    array(15, "Gilford", 1),
    array(16, "Arianna", 0)
);

// Extract strength of participant
foreach ($participants as $array) {
    $finorder[] = $array[2];
}
// Sort by strength, strongest first
array_multisort($finorder,SORT_DESC,$participants);

$order = array();
$outside = array();

// Remove participants above 'perfect' number
$remove = cleanList(sizeof($participants));
for ($r = 1; $r <= $remove; $r += 1) {
    $removed = array_shift($participants);
    $outside[] = $removed;
}

// Get corresponding bracket
$res = getBracket(sizeof($participants));
foreach ($res as $n) {
    $order[] = $n;
}

// Align bracket results with participant list
array_multisort($order, $participants);
$participants = array_combine($res, $participants);

echo "The final arrangement of participants\n";
print_r($participants);
print_r($outside);
?>

码页演示

为了获得元素插入顺序的逻辑,我使用了这种模式

而且,由于我对PHP不太熟悉,所以可能有一些方法可以缩短一些东西,但是哦,好吧,只要它起作用^^

编辑:修正了第一个参与者排序的问题,并添加了新的票号。有关没有旧票号的结果,请参见这里

EDIT2:设法将键移动到数组中;参见这里

EDIT3:我认为“额外的”参与者应该在括号之外。如果要在括号中使用null,则可以使用此方法。

EDIT4:不知怎么的,PHP版本破坏了一些东西.将其修正在下面并删除初始索引.:

代码语言:javascript
复制
<?php

    // Function generating order participants will be placed in array
    function getBracket($L) {
        // List will hold insert sequence
        $list = array();
        // Bracket will hold final order of participants
        $bracket = array();
        // The algorithm to generate the insert sequence
        for ($n = 1; $n <= $L; $n += 1) {
            // If 'perfect' number, just put it (Perfect no.s: 2, 4, 8, 16, 32, etc)
            if (int(log($n)/log(2)) || $n == 1) {
                $list[] = $n;
            // If odd number, stuff...
            } elseif ($n % 2 == 1) {
                $list[] = $list[($n-1)/2];
            // Else even number, stuff...
            } else {
                $list[] = $list[$n/2-1]+$n/2;
            }
        }

        // Insert participant order as per insert sequence
        for ($i = 1; $i <= sizeof($list); $i += 1) {
            $id = $list[$i-1]-1;
            array_splice($bracket, $id, 0, $i);
        }
        return $bracket;
    }

    // Find number of participants over 'perfect' number if any
    function cleanList($L) {
        for ($d = 1; $L > $d; $d += 1) {
            $diff = $L-pow(2,$d);
            if($diff == 0) {break;}
            if($diff < 0) {
                $diff = pow(2,$d)-$L;
                break;
            }
        }
        return $diff;
    }

    $participants = array(
        array("John", 2),
        array("Gagan", 1),
        array("Mike Tyson", 1),
        array("Gair", 1),
        array("Gale", 0),
        array("Roy Johnes", 0),
        array("Galip", 0),
        array("Gallagher", 0),
        array("Garett", 0),
        array("Nikolai Valuev", 0),
        array("Garner", 1),
    );

    // Extract strength of participant
    foreach ($participants as $array) {
        $finorder[] = $array[2];
    }
    // Sort by strength, strongest first
    array_multisort($finorder,SORT_DESC,$participants);

    $order = array();

    // Add participants until 'perfect' number
    $add = cleanList(sizeof($participants));
    for ($r = 1; $r <= $add; $r += 1) {
        $participants[] = null;
    }

    // Get corresponding bracket
    $res = getBracket(sizeof($participants));
    // Align bracket results with participant list
    foreach ($res as $n) {
        $order[] = $n;
    }
    array_multisort($order, $participants);
    $participants = array_combine($res, $participants);

    echo "The final arrangement of participants\n";
    print_r($participants);
?>

意为

毒蛇-7

票数 3
EN

Stack Overflow用户

发布于 2013-09-02 20:53:05

考虑到参与者的数量总是2的幂,这段代码应该会给出您所期望的顺序。

代码语言:javascript
复制
function getOrder($numberOfParticipants) {
    $order = array(1, 2);

    for($i = 2; $i < $numberOfParticipants; $i <<= 1) {
        $nextOrder = array();
        foreach($order as $number) {
            $nextOrder[] = $number;
            $nextOrder[] = $number + $i;
        }
        $order = $nextOrder;
    }

    return $order; // which is for instance [1, 17, 9, 25, and so on...] with 32 as argument
}

关于它的工作方式,让我们来看看当参与者数量增加一倍时会发生什么。

代码语言:javascript
复制
Participants | Order
           2 | 1   2
           4 | 1   3=1+2   2   4=2+2
           8 | 1   5=1+4   3   7=3+4   2   6=2+4   4   8=4+4
         ... |
           N | 1         X         Y         Z         ...
          2N | 1   1+N   X   X+N   Y   Y+N   Z   Z+N   ...

我使用的算法是完全相同的逻辑。我从一个只包含[1, 2]的数组开始,$i实际上是这个数组的大小。然后,我计算下一行,直到我找到一个有适当数目的参与者。

顺便提一句:$i <<= 1$i *= 2做的是一样的。您可以阅读有关位运算符的文档以获得进一步的解释。

关于强壮的运动员,如果你想保持尽可能多的随机性,这里有一个解决方案(可能不是最优的,但这是我最初想到的):

  1. 创建两个数组,一个是强数组,另一个是弱数组。
  2. 如果没有强或单个强,只需对整个数组进行洗牌,然后转到8。
  3. 如果强者多于弱者(如果在你的情况下可能发生这种情况,但最好是安全而不是抱歉),那就洗牌强者,把最后的强者和弱者放在一起,这样两个阵列的大小是相同的。
  4. 否则,用null元素填充强数组,使数组大小为2,然后对其进行洗牌。
  5. 洗牌弱者
  6. 准备足够多的组,因为它们是strongs数组中的元素,并在每个组中放入一个strongs (如果您有null元素,则没有一个),然后根据需要完成多个弱组。
  7. 洗牌
  8. 返回参与者,排序方式与以前的函数结果数组相同。

以及相应的代码:

代码语言:javascript
复制
function splitStrongsAndWeaks($participants) {
    $strongs = array();
    $weaks = array();

    foreach($participants as $participant) {
        if($participant != null && $participant[1] == 1)
            $strongs[] = $participant;
        else
            $weaks[] = $participant;
    }

    return array($strongs, $weaks);
}

function insertNullValues($elements, $totalNeeded)
{
    $strongsNumber = count($elements);
    if($strongsNumber == $totalNeeded)
        return $elements;
    if($strongsNumber == 1)
    {
        if(mt_rand(0, 1))
            array_unshift($elements, null);
        else
            $elements[] = null;
        return $elements;
    }
    if($strongsNumber & 1)
        $half = ($strongsNumber >> 1) + mt_rand(0, 1);
    else
        $half = $strongsNumber >> 1;
    return array_merge(insertNullValues(array_splice($elements, 0, $half), $totalNeeded >> 1), insertNullValues($elements, $totalNeeded >> 1));
}

function shuffleParticipants($participants, $totalNeeded) {
    list($strongs, $weaks) = splitStrongsAndWeaks($participants);

    // If there are only weaks or a single strong, just shuffle them
    if(count($strongs) < 2) {
        shuffle($participants);
        $participants = insertNullValues($participants, $totalNeeded);
    }
    else {
        shuffle($strongs);

        // If there are more strongs, we need to put some with the weaks
        if(count($strongs) > $totalNeeded / 2) {
            list($strongs, $strongsToWeaks) = array_chunk($strongs, $totalNeeded / 2);
            $weaks = array_merge($weaks, $strongToWeaks);
            $neededGroups = $totalNeeded / 2;
        }
        // Else we need to make sure the number of groups will be a power of 2
        else {
            $neededGroups = 1 << ceil(log(count($strongs), 2));
            if(count($strongs) < $neededGroups)
                $strongs = insertNullValues($strongs, $neededGroups);
        }

        shuffle($weaks);

        // Computing needed non null values in each group
        $neededByGroup = $totalNeeded / $neededGroups;
        $neededNonNull = insertNullValues(array_fill(0, count($participants), 1), $totalNeeded);
        $neededNonNull = array_chunk($neededNonNull, $neededByGroup);
        $neededNonNull = array_map('array_sum', $neededNonNull);

        // Creating groups, putting 0 or 1 strong in each
        $participants = array();            
        foreach($strongs as $strong) {
            $group = array();

            if($strong != null)
                $group[] = $strong;
            $nonNull = array_shift($neededNonNull);
            while(count($group) < $nonNull)
                $group[] = array_shift($weaks);
            while(count($group) < $neededByGroup)
                $group[] = null;

            // Shuffling again each group so you can get for instance 1 -> weak, 17 -> strong
            shuffle($group);
            $participants[] = $group;
        }

        // Flattening to get a 1-dimension array
        $participants = call_user_func_array('array_merge', $participants);
    }

    // Returned array contains participants ordered the same way as getOrder()
    // (eg. with 32 participants, first will have number 1, second number 17 and so on...)
    return $participants;
}

如果希望结果数组将括号中的数字作为索引,只需执行以下操作:

代码语言:javascript
复制
$order = getOrder(count($participants));
$participants = array_combine($order, shuffleParticipants($participants, count($order)));
票数 4
EN

Stack Overflow用户

发布于 2013-09-02 19:20:35

这个粗略的代码可能就是您想要的:

代码语言:javascript
复制
<?php

class Pair
{
    public $a;
    public $b;

    function __construct($a, $b) {
        if(($a & 1) != ($b & 1)) 
            throw new Exception('Invalid Pair');
        $this->a = $a;
        $this->b = $b;
    }
}

class Competition
{
    public $odd_group = array();
    public $even_group = array();

    function __construct($order) {
        $n = 1 << $order;
        $odd = array();
        $even = array();
        for($i = 0; $i < $n; $i += 4) {
            $odd[] = $i + 1;
            $odd[] = $i + 3;
            $even[] = $i + 2;
            $even[] = $i + 4;
        }
        shuffle($odd);
        shuffle($even);
        for($i = 0; $i < count($odd); $i += 2) {
            $this->odd_group[] = new Pair($odd[$i], $odd[$i+1]);
            $this->even_group[] = new Pair($even[$i], $even[$i+1]);
        }
        echo "Odd\n";
        for($i = 0; $i < count($this->odd_group); ++$i) {
            $pair = $this->odd_group[$i]; 
            echo "{$pair->a} vs. {$pair->b}\n";
        }
        echo "Even\n";
        for($i = 0; $i < count($this->even_group); ++$i) {
            $pair = $this->even_group[$i]; 
            echo "{$pair->a} vs. {$pair->b}\n";
        }
    }
}

new Competition(5);

?>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18559923

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档