N个人随机但均匀地分组? (姓名和性别)

时间:2017-11-19 18:17:21

标签: php mysql algorithm grouping

所以,我尝试创建一个算法(?)来将一个人分配到教室。每个班级的要求是:

  1. 至少有30人,最多45人
  2. 此人名不是“Homogen”(例如:1至3级所有人名均以字母“A”开头,而4-5级则以字母“B”开头等。)
  3. 性别也是均匀分布的
  4. 如果课程已满,剩下的人将被移至等候名单
  5. 我的数据包含唯一ID,名称和性别列。我还是新手这种东西(算法?)所以我甚至不知道从哪里开始。它甚至可能吗?我从哪里开始?我正在使用PHP,我的数据在MySQL数据库中

2 个答案:

答案 0 :(得分:0)

第1步

您需要从DateBase(所有人)获取数据

$host = '***';
$user = '***'';
$password = '***'';
$database = '***'';

$link = mysqli_connect($host, $user, $password, $database) or die("Error" . mysqli_error($link));
$query = "SELECT * FROM people";

$people = mysqli_query($link, $query) or die("Error" . mysqli_error($link));
mysqli_close($link);

第2步

Conver mysql_result to Array并将其随机播放。

$people = [];
foreach ($result as $person) {
    $people[] = $person;
}
shuffle($people);

第3步

有算法:

$count = count($people);
// Classes
$classes = [];
const MIN_SIZE = 30;
const MAX_SIZE = 45;


$maxSizeClass= $count / MIN_SIZE;
$minSizeClass= $count / MAX_SIZE;

$countClasses = max(ceil($minSizeClass), floor($maxSizeClass));
$currentCountClass = $count / $countClasses;

$tmpClass = [];
foreach ($people as $person) {
    if (count($tmpClass) < $currentCountClass) {
        $tmpClass[] = $person;
    } else {
        $classes[] = $tmpClass;
        $tmpClass = [];
    }
}

if (count($tmpClass) >= MIN_SIZE) {
    $classes[] = $tmpClass;
    $tmpClass = [];
}

foreach ($tmpClass as $index => $person) {
    foreach ($classes as &$class) {
        if (count($class) < MAX_SIZE) {
            $class[] = $person;
            // be careful, PHP7 is OK
            unset($tmpClass[$index]);
            continue 2;
        }
    }
}

// persons awaiting distribution
$waitingQueue = $tmpClass;

第4步

结果是:

$waitingQueue - 等待分发的人

$classes - 有人的课程

答案 1 :(得分:0)

$letters = array('a','b',....,'y','z');
foreach($letters as $letter){
    $sql['male'] = "SELECT * FROM people_table WHERE person_name LIKE '".$letter."%' AND person_gender = 'male' ORDER BY person_name";
    $sql['female'] = "SELECT * FROM people_table WHERE person_name LIKE '".$letter."%' AND person_gender = 'female' ORDER BY person_name";
    foreach($sql as $key => $query){
        $results[$key] = $connection->query($query);
        for($i = 0; $i < $results[$key]->num_rows; $i++){
            $people[$letter][$key][] = results->fetch_array(MYSQLI_ASSOC);
        }
    }
}

这里我们列出了按性别列出的人员名单......现在我们可以循环并按成对插入一个男人和一个女人。如果对列表的count();小于30,则人们等待更多。如果大于44(因为对不可能有45个人,当然如果我不想错过这个问题)那么将这个44保存在类数组$class[$letter]中,你可以看到每个类信件。要了解您总共有多少课程,可以使用count($class);,或者如果您想知道您可以执行特定字母的多少课程count($class[$letter]);

您可以重做foreach数组中的其他$letters,或者只是将循环放在上面的foreach中以创建类数组。 在最后的foreach($letters as $letter){}内:

if( !(count($people[$letter][$key]) < 15 OR count($people[$letter][$key]) < 15) ){
    $she = count($people[$letter]['female'];
    $he = count($people[$letter]['male'];
    if($she < $he){
        for($i = 0; $i < 2*count($she); $i++){
            $class[$letter][$i] = $people[$letter]['female'][$i];
            $class[$letter][$i+1] = $people[$letter]['male'][$i];
            $i++;//Important to avoid replace values!
        }
    } else {
        for($i = 0; $i < 2*count($he); $i++){
            $class[$letter][$i] = $people[$letter]['female'][$i];
            $class[$letter][$i+1] = $people[$letter]['male'][$i];
            $i++;//Important to avoid replace values!
        }
}

较大的if中的假布尔值意味着无法创建具有均匀分布的此字母的类。您可以再次循环以使每个类都在数组的条目中。