php 使用随机数填充数组,同时遵守指定的总和、计数和数字边界

ntjbwcob  于 2023-01-04  发布在  PHP
关注(0)|答案(2)|浏览(178)

我必须用随机数填充一个数组以满足以下几个条件:
1.结果数组中的元素数必须与指定的数字匹配。
1.结果数组中的数字之和必须等于指定的数字。
1.必须在指定的下限和上限之间选择随机数。
例如:

  • 数组的和:130
  • 数组元素总数:3
  • 随机整数的下界:23
  • 随机整数的上限:70

可能结果:

array(23, 70, 37)

现在该怎么办?如何拆分/除我的号码?
我从这个(伪代码)开始:

i=0;
while(sum(number) > 0 and i < arraykeys){
    x = randomize(from, to)
    number = number - x
    myarray[i] = x
    i++
}
yyyllmsg

yyyllmsg1#

这应该对你有用:

代码说明

1.* * 可操作性**
我们需要检查的第一件事是,是否可以从范围中的数字构建目标:

if(checkWorkability($result, $goal, $amountOfElementsLeft, $scope))

意味着它只使用可能的最高值,并查看它是否大于目标。
1.* * While循环**
在while循环中,我们需要检查是否还有可以使用的元素:

while($amountOfElementsLeft > 0)

1.* * 范围调整**
每次迭代我们都需要检查是否需要调整范围,这样在最后我们就能够建立目标。
这意味着如果当前的数字总和+可能的最大数字大于目标值,我们需要使作用域的最大值更小。
另一方面,当我们不能再达到目标时,我们需要使作用域的最小值更大。

代码

<?php

    $goal = 130;
    $amountOfElementsLeft = 3;
    $scope = [23, 70];

    $result= [];

    function adjustScope(array $result, $goal, $amountOfElementsLeft, $scope) {

        $newScope = $scope;

        if($amountOfElementsLeft == 1) {
            $leftOver = $goal - array_sum($result);
            return [$leftOver, $leftOver];
        }

        if((($goal - (array_sum($result) + $scope[1])) / ($amountOfElementsLeft - 1)) < $scope[0])
            $newScope[1] = (int) ($goal - array_sum($result)) / ($scope[0] * ($amountOfElementsLeft - 1));
        elseif(($adjustTop = $goal - array_sum($result)) < $scope[1])
            $newScope[1] = $adjustTop;

        if(($adjustBottom = $goal - (array_sum($result) + $scope[0] + (($amountOfElementsLeft - 1) * $scope[1]))) < $goal && $adjustBottom > 0)
            $newScope[0] = $scope[0] + $adjustBottom;

        return $newScope;

    }

    function checkWorkability(array $result, $goal, $amountOfElementsLeft, $scope) {
        if(array_sum($result) + $amountOfElementsLeft * $scope[1] >= $goal)
            return TRUE;
        return FALSE;
    }

    if(checkWorkability($result, $goal, $amountOfElementsLeft, $scope)) {
        while($amountOfElementsLeft > 0) {
            $scope = adjustScope($result, $goal, $amountOfElementsLeft, $scope);

            $result[] = rand($scope[0], $scope[1]);
            $amountOfElementsLeft--;

        }
    }

    print_r($result);
    echo array_sum($result);

?>

可能的产出:

Array
(
    [0] => 58
    [1] => 30
    [2] => 42
) -> 130
Array
(
    [0] => 35
    [1] => 54
    [2] => 41
) -> 130
Array
(
    [0] => 52
    [1] => 51
    [2] => 27
) -> 130
beq87vna

beq87vna2#

我编写了一个自定义函数,以实现可移植性,并有意义地实现一些保护条件,当传入参数使所需结果不可能实现时,这些条件会抛出异常。
1.循环一次不超过$count次--这是因为返回数组中的最后一个元素是由所需的总和与随机获取的值之和之间的差值确定的。
1.调整$scope数组的下限和上限(如果需要),以确保成功填充返回数组。
1.获取一个随机整数,将其推入返回数组,然后从$total中减去它。
1.当循环进程完成时,将剩余的$total值作为返回数组中的最后一个元素压入。
代码:(Demo

function getRandWithStipulations(int $total, int $count, array $scope): array
{
    if ($scope[0] > $scope[1]) {
        throw new Exception('Argument 3 (\$scope) is expected to contain a minimum integer then a maximum integer.');
    }
    if ($scope[0] * $count > $total) {
        throw new Exception('Arguments 2 (\$count) and 3 (\$scope) can only exceed argument 1 (\$total).');
    }
    if ($scope[1] * $count < $total) {
        throw new Exception('Arguments 2 (\$count) and 3 (\$scope) cannot reach argument 1 (\$total).');
    }
    $result = [];
    for ($x = 1; $x < $count; ++$x) { // count - 1 iterations
        $scope[0] = max($scope[0], $total - ($scope[1] * ($count - $x)));
        $scope[1] = min($scope[1], $total - ($scope[0] * ($count - $x)));
        $rand = rand(...$scope);
        $result[] = $rand;
        $total -= $rand;
    }
    $result[] = $total;
    return $result;
}
try {
    var_export(
        getRandWithStipulations(
            130,
            3,
            [23, 70]
        )
    );
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage();
}

一些随机结果:

  • [60, 34, 36]
  • [23, 59, 48]
  • [67, 36, 27]
  • [47, 23, 60]

相关问题