【问题标题】:Split a number into three buckets with constraints将一个数字分成三个有约束的桶
【发布时间】:2011-11-15 15:58:46
【问题描述】:

有没有一种很好的算法可以将随机生成的数字分成三个桶,每个桶都有关于它们可能包含多少总数的限制。

例如,假设我随机生成的数字是 1,000,我需要将其拆分为桶 a、b 和 c。

These ranges are only an example. See my edit for possible ranges.
Bucket a may only be between 10% - 70% of the number (100 - 700)
Bucket b may only be between 10% - 50% of the number (100 - 500)
Bucket c may only be between 5% - 25% of the number (50 - 250)
a + b + c must equal the randomly generated number 

您希望分配的数量是完全随机的,因此存储桶 a 达到其最大值的机会与存储桶 c 的机会相同,并且所有三个存储桶的概率都在其百分比平均值附近。

编辑:以下情况很可能总是正确的:a + b + c 100% 的高端。这些百分比仅表示可接受的 a、b 和 c 值。在 a 为 10% 而 b 和 c 为最大值(分别为 50% 和 25%)的情况下,必须重新分配数字,因为总数不等于 100%。这正是我试图通过找到一种方法一次性分配这些数字来避免的确切情况。

我想找到一种方法,一次性在它们的范围内随机选择这些数字。

【问题讨论】:

  • 如果我们选择第一个bucket的10%,那么我们能得到的最大数是(10%+50%+25%)*x = 85%的初始数。所以 a+b+c 不能成立。
  • 抱歉,不清楚。我已经更新了帖子。

标签: algorithm probability combinatorics


【解决方案1】:

问题等同于在 N 维对象中选择一个随机点(在您的示例中 N=3),该对象由方程式定义(在您的示例中):

0.1  <= x  <= 0.7
0.1  <= y  <= 0.5
0.05 <= z  <= 0.25
x + y + z   = 1 (*)

很明显,由于最后一个等式 (*),其中一个坐标是多余的,即为 x 和 y 选取值指示 z。

消除 (*) 和其他方程之一,我们得到一个 (N-1) 维框,例如

0.1 <= x  <= 0.7
0.1 <= y  <= 0.5

被不等式切割

0.05 <= (1 - x - y) <= 0.25 (**)

源自 (*) 和 z 的方程。这基本上是一个穿过盒子的斜条纹。

为了使结果一致,我只是重复采样(N-1)维框,并接受第一个满足(**)的采样点。单次通过的解决方案最终可能会产生有偏差的分布。

【讨论】:

  • 这个问题是如果 x 和 y 都是 0.1。这意味着 z 必须为 0.8,超出其可接受的范围。
【解决方案2】:

更新:是的,你是对的,结果不是均匀分布的。

假设您的百分比值是自然数(如果这个假设是错误的,您不必进一步阅读:)在这种情况下,我没有解决方案。

让我们将事件e 定义为3 个值的元组(每个桶的百分比):e = (pa, pb, p c)。接下来,创建所有可能的事件 en。您在这里拥有的是一个由离散数量的事件组成的元组空间。所有可能的事件都应该具有相同的发生可能性。

假设我们有一个函数 f(n) => en。然后,我们所要做的就是取一个随机数 n 并一次性返回 en

现在,问题仍然是创建这样一个函数f :)

在伪代码中,一个非常慢的方法(仅用于说明):

function f(n) {
    int c = 0
    for i in [10..70] {
        for j in [10..50] {
            for k in [5..25] {
                if(i + j + k == 100) {
                    if(n == c) {
                        return (i, j, k) // found event!
                    } else {
                        c = c + 1
                    }
                }
            }
        }
    }
}

您所知道的是单程解决方案,但问题只是被移开了。函数 f 非常慢。但是您可以做得更好:我认为如果您正确设置范围并计算偏移量而不是遍历您的范围,您可以更快地计算所有内容。

这够清楚了吗?


首先,您可能必须调整您的范围。桶中的 10% a 是不可能的,因为您无法让条件 a+b+c = number 保持。

关于您的问题:(1) 在您的范围内为存储桶 a 选择一个随机数,然后 (2) 使用最小和最大百分比更新存储桶 b 的范围(您应该只缩小范围)。然后 (3) 为桶 b 选择一个随机数。最后c应该计算出你的条件成立(4)。

例子:

    n = 1000
(1) a = 40%
(2) range b [35,50], because 40+35+25 = 100%
(3) b = 45%
(4) c = 100-40-45 = 15%

或者:

    n = 1000
(1) a = 70%
(2) range b [10,25], because 70+25+5 = 100%
(3) b = 20%
(4) c = 100-70-20 = 10%

检查所有事件是否均匀分布。如果这应该是一个问题,您可能希望在第 2 步中随机化范围更新。

【讨论】:

  • 我已经更新了问题以解决存在 10% 的可能性和问题。
猜你喜欢
  • 1970-01-01
  • 2015-01-23
  • 2012-04-06
  • 2013-03-17
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
  • 2015-12-25
  • 1970-01-01
相关资源
最近更新 更多