且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在数组新的随机生成的值替换重复值

更新时间:2023-02-02 22:19:42

好吧,这个问题实际上是围绕着线性序列。为1的最小值考虑序列:

Ok, this problem actually revolves around linear sequences. With a minimum value of 1 consider the sequence:

f(n) = 1 + 2 + ... + n - 1 + n

这样的序列的总和等于:

The sum of such a sequence is equal to:

f(n) = n * (n + 1) / 2

所以对于n = 4,作为一个例子,总和为10。这意味着,如果你选择4个不同的号码的最小总无零点和没有底片10。现在转到反向:如果你有一个总的10和4号,那么只有一个的组合的的(1,2,3,4)。

so for n = 4, as an example, the sum is 10. That means if you're selecting 4 different numbers the minimum total with no zeroes and no negatives is 10. Now go in reverse: if you have a total of 10 and 4 numbers then there is only one combination of (1,2,3,4).

所以,首先你需要检查你的总数至少高达该下限。如果其含量是没有组合。如果是相等的,有precisely一种组合。如果是更高它变得更加复杂。

So first you need to check if your total is at least as high as this lower bound. If it is less there is no combination. If it is equal, there is precisely one combination. If it is higher it gets more complicated.

现在想象你的约束共12个与4个数字。我们已经建立了f(4)= 10。但是,如果第一个(最低)数量为2?

Now imagine your constraints are a total of 12 with 4 numbers. We've established that f(4) = 10. But what if the first (lowest) number is 2?

2 + 3 + 4 + 5 = 14

因此​​,第一个数字不能高于1你知道你的第一个数字。现在你产生,共有11(即12 - 1)3个数字的序列。

So the first number can't be higher than 1. You know your first number. Now you generate a sequence of 3 numbers with a total of 11 (being 12 - 1).

1 + 2 + 3 = 6
2 + 3 + 4 = 9
3 + 4 + 5 = 12

第二数目必须2,因为它不能是一个。它不可能是3,因为三个数字开始3最低金额是12,我们必须增加至11。

The second number has to be 2 because it can't be one. It can't be 3 because the minimum sum of three numbers starting with 3 is 12 and we have to add to 11.

现在我们发现,加起来9两个数字(12 - 1 - 2)。用3是最低的。

Now we find two numbers that add up to 9 (12 - 1 - 2) with 3 being the lowest possible.

3 + 4 = 7
4 + 5 = 9

第三数目可以是3或4。第三号找到的最后一个是固定的。的两个可能的组合是:

The third number can be 3 or 4. With the third number found the last is fixed. The two possible combinations are:

1, 2, 3, 6
1, 2, 4, 5

您可以变成一个通用算法这一点。考虑这个递归实现:

You can turn this into a general algorithm. Consider this recursive implementation:

$all = all_sequences(14, 4);
echo "\nAll sequences:\n\n";
foreach ($all as $arr) {
  echo implode(', ', $arr) . "\n";
}

function all_sequences($total, $num, $start = 1) {
  if ($num == 1) {
    return array($total);
  }
  $max = lowest_maximum($start, $num);
  $limit = (int)(($total - $max) / $num) + $start;
  $ret = array();
  if ($num == 2) {
    for ($i = $start; $i <= $limit; $i++) {
      $ret[] = array($i, $total - $i);
    }
  } else {
    for ($i = $start; $i <= $limit; $i++) {
      $sub = all_sequences($total - $i, $num - 1, $i + 1);
      foreach ($sub as $arr) {
        array_unshift($arr, $i);
        $ret[] = $arr;
      }
    }
  }
  return $ret;
}

function lowest_maximum($start, $num) {
  return sum_linear($num) + ($start - 1) * $num;
}

function sum_linear($num) {
  return ($num + 1) * $num / 2;
}

输出:

All sequences:

1, 2, 3, 8
1, 2, 4, 7
1, 2, 5, 6
1, 3, 4, 6
2, 3, 4, 5

一个实现,这将是把所有的序列,并选择一个随机的。这有同样加权所有可能的组合,这可能会或可能不会有用或有必要,你在做什么优势。

One implementation of this would be to get all the sequences and select one at random. This has the advantage of equally weighting all possible combinations, which may or may not be useful or necessary to what you're doing.

这会变得笨拙大总计或大量的元素,在这种情况下,上述的算法可修改成返回一个随机元素的范围从 $启动 $限额,而不是每一个值。

That will become unwieldy with large totals or large numbers of elements, in which case the above algorithm can be modified to return a random element in the range from $start to $limit instead of every value.