生成具有固定总和和约束的随机整数

时间:2016-01-29 00:03:37

标签: random

如何生成6个随机整数,最多可加8,每个整数小于或等于2?

例如。 1,2,1,2,2,0

到目前为止,我已经找到了一种方法,它给出了具有固定和的随机整数,但是如何对这些整数施加约束。

3 个答案:

答案 0 :(得分:3)

这个怎么样:

  1. 以全零开始数组。
  2. 随机选择一个数组索引,并在数组中的该位置添加一个。如果它已经是两个,请不要这样做,重试直到成功。
  3. 执行第8步
  4. 这不会在[0,2]上产生均匀分布的整数(但你没有说出你需要的分布),数字会偏向阵列中相等的高度。

答案 1 :(得分:2)

首先,并非所有这些都是真正随机的,因为这些要求会产生一些必要的东西。

例如,必须至少有两个2,以便集合{0,1,2}中的6个总数使其成为8.所以我们的两个结束整数是预先确定的。也许不要因此浪费能量来解决它们。所以这启动我们在2,2,?,?,?,?。

现在让我们面临一个挑战,包括从集合{0,1,2}中得到4个等于4的数字。可能的组合是(不计算0' s)两个2' s,一个2和2个1,以及4个1。字面上只有3种可能的组合。因此,将它们设置为数组并随机选择一个是有意义的......这些数组可以从我们已经知道的两个2开始。所以:

var possibles = [
    [2,2,2,2,0,0],
    [2,2,2,1,1,0],
    [2,2,1,1,1,1]
];

var randomInd = Math.floor( Math.random()*possibles.length ); // random number from 0-2
var myArr = possibles[randomInd]; // picks a random entry from possibles

现在我们已经有了一个随机数组,其中包含可能出现故障的方法,我们只需将其改组。我们可以使用标准的混洗功能:

function shuffle(arr)
{
    var curInd = arr.length, tempVal, randInd;
    while (0 !== curInd) {
        randInd = Math.floor(Math.random()*curInd);
        curInd -= 1;
        tempVal = arr[curInd];
        arr[curInd] = arr[randInd];
        arr[randInd] = tempVal;
    }
}

shuffle(myArr);
alert(myArr); // will give "random" sequence

你也可以"体重"通过在possibles数组中更好地表示它们的某些组合(即,使某个组合的2个条目而不是1)。

注意 - 我没有看到任何特定语言,所以对于任何好奇的人来说都是javascript。可以看到JSFiddle在这里工作:https://jsfiddle.net/6xaeLp4g/

答案 2 :(得分:1)

我建议使用命中注意法来保证满足约束的生成序列的均匀分布。很容易发现,{0,1,2}中6个随机整数的概率加起来大约为12.3%,因此在命中之前不需要太多的试验。这是一个Python实现:

import random

def randNums(n,a,b,s):
    #finds n random ints in [a,b] with sum of s
    hit = False
    while not hit:
        total, count = 0,0
        nums = []
        while total < s and count < n:
            r = random.randint(a,b)
            total += r
            count += 1
            nums.append(r)
        if total == s and count == n: hit = True
    return nums

以下是5次运行的输出:

>>> for i in range(5): print(randNums(6,0,2,8))

[2, 1, 0, 2, 1, 2]
[0, 2, 2, 1, 1, 2]
[2, 2, 0, 2, 0, 2]
[2, 2, 0, 1, 1, 2]
[1, 2, 1, 1, 1, 2]

On Edit:我对确切的概率感到好奇,所以编写了一个详尽列举所有可能性的程序。 {0,1,2}中长度为6的随机序列可以被认为是在基数3中写入0到3 ^ 6-1 = 728的随机整数。只需计算该范围内基数为3的数字和,并查看其中= 8:

def toBase3(n):
    digits = []
    q,r = divmod(n,3)
    while q > 0:
        digits.append(r)
        q,r = divmod(q,3)
    digits.append(r)
    return ''.join(str(i) for i in reversed(digits))

def dsum(s):
    return sum(int(d) for d in s)

hits = []
for n in range(729):
    s = toBase3(n)
    if dsum(s) == 8: hits.append(s)

hits = [('0'*(6-len(s)))+s for s in hits] #left-pad with '0' if needed

s = ''.join(hits)

print("%d valid sequences for prob. of %f" % (len(hits),len(hits)/3.0**6))
print("%d zeros in those sequences for a prob. of %f" % (s.count('0'),s.count('0')/540.0))
print("%d ones in those sequences for a prob. of %f" % (s.count('1'),s.count('1')/540.0))
print("%d twos in those sequences for a prob. of %f" % (s.count('2'),s.count('2')/540.0))

输出:

90 valid sequences for prob. of 0.123457
90 zeros in those sequences for a prob. of 0.166667
180 ones in those sequences for a prob. of 0.333333
270 twos in those sequences for a prob. of 0.500000

作为奇怪的好奇心,这样一个长度为6的随机序列总和为8,显示更多小数位的概率是

90/729 = 0.123456790 (repeating)

我没有意识到令人愉悦的十进制0.1234567有一个很好的概率解释。很遗憾8不在7之后。