如何创建平均分布的三个组?

时间:2014-08-16 02:10:38

标签: php mysql

对于网站应用程序,我需要组成三个随机组。用户他/她自己无法评分(因此不能成为该组的一部分)。总会有至少4个用户。

例如,如果有5个用户,我会有一个数组:Array(0,1,2,3,4),我希望输出为(其中键是用户和数据)是3)的小组。

Array(
[0 : 1,2,3],
[1 : 0,2,4],
[2 : 1,4,3],
[3 : 0,1,4],
[4 : 0,2,3]
);

请注意,用户从不在群组中,每个用户都被分配了3次。

您不能简单地随机选择用户到组,因为它可能被分配超过3次并强制某些组在该组中少于3个用户。

我希望我能恰当地解释这个问题,并且有人能够提供帮助。

这是一些代码,它将三个随机数放在一个字典中并且[0,1,2,3]可以正常工作,但是(很可能)会因为数字不均匀分布而失败(并且会继续)永远在while循环,因为没有可能的数字。)

$rows = range(0,3);
$array_size = count($rows);
$peers_array = Array();
$number_count = array_fill(0, $array_size, 0);

foreach($rows as $index => $row){
    $randomNumbers = Array();
    for($x = 0; $x < 3; ++$x){
        $randomNumber = rand(0, $array_size-1);
        while($randomNumber==$index or in_array($randomNumber, $randomNumbers) or $number_count[$randomNumber]>2)
            $randomNumber = rand(0, $array_size-1);
        $number_count[$randomNumber]++;
        $randomNumbers[] = $randomNumber;
    }
    $peers_array[$index] = $randomNumbers;
}
print_R( $peers_array);

3 个答案:

答案 0 :(得分:2)

好的,我已经提出了自己的解决方案。花了一点点思考,但多亏了建议我能够提出这个解决方案:

首先它生成一个从0到用户数量的范围 - 1(例如,对于5,它会给出[0,1,2,3,4])然后每次都将列表移动一个(例如[0] ,1,2,3,4]成为[4,0,1,2,3])然后它将每个元素放在数组的给定索引处并将其放入一个组中(所以如果我只想要组2将给出0:[0,4] 1:[0,1] 2:[2,1]等等......)。然后,您可以在用户数量之间切换顺序 - 组的大小,不要只相信我。这可以保证所有数字出现的次数相同,但仍然会使订单随机化。

以下几行可以实现这一目标:

function getUsers($user_num, $groups_of){
    $index_list = range(0,$user_num-1);
    $random_indexes = range(0,$user_num-1);
    shuffle($random_indexes);

    $groups = array();
    foreach($index_list as $user_num)
        $groups[] = array($random_indexes[$user_num]);

    for($i = 0; $i<($groups_of-1); ++$i){
        array_unshift($index_list, array_pop($index_list)); //puts the last element first

        foreach($index_list as $index => $user_num)
            $groups[$index][] = $random_indexes[$user_num];
    }

    $shift_number = rand(1, ($len_users-$groups_of));
    for($i = 0; $i<$shift_number; ++$i)
        array_unshift($groups, array_pop($groups));

    return $groups
}

答案 1 :(得分:0)

我在想array_pop这是一个很好的方法,它适用于问题的第一部分,很容易获得当前项目并确保它不适用于下一部分,然而你最终必须跟踪太多活动部件。

最后选择array_diff从原始数组中删除当前行。

$rows = range(0,15);
$results = array();
foreach ($rows as $row) {
    $others = array_diff($rows,array($row));
    shuffle($others);
    $results[$row] = array_slice(array_values($others),0,3);
}
var_dump($results);

结果:

array (size=16)
  0 => 
    array (size=3)
      0 => int 9
      1 => int 1
      2 => int 10
  1 => 
    array (size=3)
      0 => int 10
      1 => int 11
      2 => int 14
  2 => 
    array (size=3)
      0 => int 3
      1 => int 15
      2 => int 14
  3 => 
    array (size=3)
      0 => int 9
      1 => int 4
      2 => int 1
      etc...

答案 2 :(得分:0)

我认为:(概括)

function getUsers($users,$groups_of){
    $result = array();
    for($i = 0; $i < $users; $i++){
        $usernums = array();
        while(count($usernums) < $groups_of){ 
            $randomNumber = rand(0, $users-1);
            if($i != $randomNumber && !in_array($randomNumber, $usernums)){
                $usernums[] = $randomNumber;
            }
        }
        $result[$i] = $usernums;
    }
    return $result;
}


$users = 5;
$groups_of = 3;
print_r(getUsers($users,$groups_of));