php 在指定的约束条件内使用随机数量填充数据集

gkn4icbw  于 2023-11-16  发布在  PHP
关注(0)|答案(2)|浏览(87)

我试图从一个大的球员名单中创建一个由11名球员组成的梦幻板球队。
对于球队,我对每种类型的球员都有基本的最低和最高要求。我给他们分配了这样的值:

$min_wicket_keeper = 1;
$min_batsman = 3;
$min_all_rounders = 1;
$min_bowlers = 2;

$max_wicket_keeper = 3;
$max_batsman = 5;
$max_all_rounders = 5;
$max_bowlers = 4;

字符串
我有这样的球员:

$total_wicket_keepers = 2;
$total_batsman = 6;
$total_all_rounders = 5;
$total_bowlers = 5;


你可以看到我总共有18个玩家,现在我想创建一个11人的团队,分配随机类型的玩家--记住玩家的最小和最大要求。
实施例1

$wicket_keeper_limit = 1;
$batsman_limit = 4;
$all_rounder_limit = 4;
$bowler_limit = 2;
//so total 11


实施例2

$wicket_keeper_limit = 2;
$batsman_limit = 3;
$all_rounder_limit = 3;
$bowler_limit = 3;
//so total 11


我想为每种类型分配一个随机数,但总数应该是11,不应该低于最低要求,不应该大于然后为每种类型的最大限制后可用的球员总数。
我试过这样的代码

$min_wicket_keeper = 1;
$min_batsman = 3;
$min_all_rounders = 1;
$min_bowlers = 2;

$max_wicket_keeper = 3;
$max_batsman = 5;
$max_all_rounders = 5;
$max_bowlers = 4;

$total_wicket_keepers = 2;
$total_batsman = 6;
$total_all_rounders = 5;
$total_bowlers = 5;

$total_players_match = $total_wicket_keepers+$total_batsman+$total_all_rounders+$total_bowlers;

echo $total_players_match;

if ($total_players_match > 11) {
    $remain_players = 11;
    if ($total_wicket_keepers > $min_wicket_keeper) {
        $wicket_keeper_limit = rand($min_wicket_keeper,$total_wicket_keepers);
        $remain_players = $remain_players-$wicket_keeper_limit;
    } else {
        $wicket_keeper_limit = $total_wicket_keepers;
        $remain_players = $remain_players-$wicket_keeper_limit;
    }
        
    echo "WK: ".$wicket_keeper_limit." REMAIN: ".$remain_players."<br>";
        
    if ($total_batsman>$min_batsman) {
        $batsman_limit = rand($min_batsman,$total_batsman);
        $remain_players = $remain_players-$batsman_limit;
            
        if ($remain_players > ($total_bowlers + $total_all_rounders)) {
            $batsman_limit = ($min_batsman + $remain_players) - ($total_bowlers+$total_all_rounders);
            $remain_players = $remain_players-$batsman_limit;
        }
            
    } else {
        $batsman_limit = $total_batsman;
        $remain_players = $remain_players-$batsman_limit;
    }
        
    echo "BT: " . $batsman_limit . " REMAIN: " . $remain_players . "<br>";
        
    if ($total_bowlers > $min_bowlers) {
        $bowler_limit = rand($min_bowlers, $total_bowlers);
        $remain_players = $remain_players - $bowler_limit;
            
        if ($remain_players > $total_all_rounders) {
            $bowler_limit = $total_bowlers;
            $remain_players = $remain_players - $bowler_limit;
        }

    } else {
            $bowler_limit = $total_bowlers;
        $remain_players = $remain_players - $bowler_limit;
    }
        
    echo "BOL:" . $bowler_limit . " REMAIN:" . $remain_players . "<br>";
        
    $all_rounder_limit = $remain_players;
        
    echo "ALL: " . $all_rounder_limit . " REMAIN: " . $remain_players . "<br>";
        
} else {
    $wicket_keeper_limit = $total_wicket_keepers;
    $batsman_limit = $total_batsman;
    $all_rounder_limit = $total_all_rounders;
    $bowler_limit = $total_bowlers;
}
    
echo "WK:" . $wicket_keeper_limit . "<br>";
    echo "BT:" . $batsman_limit . "<br>";
    echo "BO:" . $bowler_limit . "<br>";
    echo "AL:" . $all_rounder_limit . "<br>";


但它没有遵循我的最低和最高要求。有时我得到保龄球为0,有时我得到所有圆高达6。
这是Online Fiddle Link

**编辑:**根据评论,我应该清楚,我将生成多个团队,将上述代码放入while循环中,就像50个团队一样,每个类型都有不同/随机的球员,比如有些团队有5个击球手,有些团队只有3个击球手。

当我将得到上述代码的工作,我会稍后从我的数据库中得到球员根据限制,我已经为每种类型。

ozxc1zmp

ozxc1zmp1#

我很抱歉,但你的代码对我来说太多了,无法处理。根据你的条件,我写了以下代码:

<?php
// Remapped your variables because it was too much
$constraints = [
    'wicket_keeper' => ['min' => 1, 'max' => 3],
    'batsman'       => ['min' => 3, 'max' => 5],
    'all_rounders'  => ['min' => 1, 'max' => 5],
    'bowlers'       => ['min' => 2, 'max' => 4],
];

// These are the current values to assign
$values = [
    'wicket_keeper' => 2,
    'batsman'       => 6,
    'all_rounders'  => 5,
    'bowlers'       => 5,
];

// The first problem is that the maximums should be adjusted to the values we have
foreach ($values as $key => $value) {
    if ($value < $constraints[$key]['max']){
        $constraints[$key]['max'] = $value;
    }
}

// Vice versa we need to do this for the minimums
// I now did this manually, but I think you get the point
$result = [
    'wicket_keeper' => 1,
    'batsman'       => 3,
    'all_rounders'  => 1,
    'bowlers'       => 2,
];

// We keep track of possible options
$options = array_keys($result);

// Init
$totalPlayers = 0;
$max = 0;

// This is minus 7 because of your minimum requirements, also done manually
// But of course you can calculate this as well.
$teamLimit = 11 - 7;
while($totalPlayers < $teamLimit) {
        // Pick a random type
        $random = rand(0, count($options) - 1);

        // Get key
        $key = $options[$random];

        // Add one player to the random type
        $result[$key] += 1;
        $totalPlayers++;

        // Check if max is reached
        // If so, remove it from possible options
        if ($result[$key] >= $constraints[$key]['max']){
            unset($options[$key]);
        }
}

var_dump($result);

字符串
我希望评论足够清楚。
Live example

tcbh2hod

tcbh2hod2#

您可以将此脚本构建为单个函数/方法,或者更好的方法是实践单一责任原则,并使用多个函数/方法执行一个任务。为了避免过多地扩展代码片段,我将仅将我的建议显示为多责任函数。

  • 传递您的团队创建设置。
  • 实现逻辑保护条件,以在设置阻止填充整个团队时向您发出警报。
  • 对您的总玩家池应用最大限制。
  • 作为一种捷径,用所有指定的最小值为您的团队播种。
  • 在一个循环中随机选择一个位置,并在池中“消耗”该位置,以便位置永远不会从池中透支。
  • 当组已满或池为空时,终止循环。
  • 返回已填充的团队或在团队无法完全填充时提醒用户。

产品编号:(Demo

function randomizeTeam(
    int $teamSize,
    array $positionPool,
    array $positionMins = [],
    array $positionMaxs = []
): array {
    // guard conditions
    foreach ($positionMins as $pos => $min) {
        if (!key_exists($pos, $positionPool) || $positionPool[$pos] < $min) {
            throw new Exception('Position pool cannot accommodate minimum required positions');
        }
    }

    // input preparation
    foreach ($positionMaxs as $pos => $max) {
        if (key_exists($pos, $positionPool) && $positionPool[$pos] > $max) {
            $positionPool[$pos] = $max;
        }
    }
    
    // seed team
    $team = [];
    $sum = 0;
    foreach ($positionPool as $pos => &$pool) {
        $team[$pos] = $positionMins[$pos] ?? 0;
        $pool -= $team[$pos];
        if (!$pool) {
            unset($positionPool[$pos]); // remove exhausted pool
        }
        $sum += $team[$pos];
    }
    
    // add random positions
    while ($sum < $teamSize && $positionPool) {
        $pos = array_rand($positionPool);
        ++$team[$pos];
        --$positionPool[$pos];
        if (!$positionPool[$pos]) {
            unset($positionPool[$pos]); // remove exhausted pool
        }
        ++$sum;
    }

    // another guard condition
    if (array_sum($team) < $teamSize) {
        throw new Exception('Position pool was exhausted before filling team');
    }

    return $team;
}

var_export(
    randomizeTeam(
        11,
        [
            'wicket_keeper' => 2,
            'batsman'       => 6,
            'all_rounders'  => 5,
            'bowlers'       => 5,
        ],
        [
            'wicket_keeper' => 1,
            'batsman'       => 3,
            'all_rounders'  => 1,
            'bowlers'       => 2,
        ],
        [
            'wicket_keeper' => 3,
            'batsman'       => 5,
            'all_rounders'  => 5,
            'bowlers'       => 4,
        ]
    )
);

字符串
潜在输出:

array (
  'wicket_keeper' => 2,
  'batsman' => 4,
  'all_rounders' => 2,
  'bowlers' => 3,
)


一些补充说明:

  • 以数组形式声明输入数据是理想的,这样您就可以享受循环和数组函数的动态好处,同时避免变量变量。
  • 上述脚本被设计为允许可扩展的位置池并且允许不需要提及主池中的所有位置的最小和/或最大位置约束。

相关问题