1

我会尽力解释这一点。我需要根据每个项目中剩余的项目数量生成一个随机值(颜色)。

假设我有 5 种颜色,每种颜色有 10 个可用点:

Red = 10
Blue = 10
Green = 10
Yellow = 10
Black = 10

我想获得第一个随机颜色,每种颜色都有相同的机会,因为它们都有 10 个可用点。然后,如果选择的第一个值是红色,那么列表将如下所示

Red = 9
Blue = 10
Green = 10
Yellow = 10
Black = 10

然后下一个随机值将使红色的权重略低,因为其他颜色中可用的斑点更高。假设 Red 再次被选中,那么列表将如下所示:

Red = 8
Blue = 10
Green = 10
Yellow = 10
Black = 10

所以下一轮的权重会更低。

基本上我希望每个地点都有平等的机会被平等地挑选,但平均分配地点(不按顺序排列)。

颜色可能多于或少于 5 种,可用的点数最多可达 1000 个。数据将存储在数据库中,但每秒可能有多个点请求,因此也感谢有关如何存储此数据的任何建议。一旦请求一个点,它就会从颜色组中删除。

非常感谢!

4

3 回答 3

0

由于您想将点存储在数据库中,因此我将采用不同于其他解决方案的另一种方法。

要对其进行建模,以便多个线程可以各自采用可用的颜色,您最好有一个点表,将它们的颜色指示为集合或外键,以及具有唯一键和默认 NULL 的租约 ID。

您可以通过首先使用租约 ID (uuid) 更新尚未租用的随机行来选择随机元素。从那里开始,其他请求不能再选择那个,您可以通过租约 ID 进行选择查询以找出它是什么颜色。这将确保不会出现竞争条件,并且您可以使用基于行的锁定同时为多个客户端提供服务。

对于 10,000 个点,您可以存储一个颜色和一个租约 ID,因此它会小于 80kB。整个表将始终在缓存中。

于 2013-07-30T00:09:19.007 回答
0

您可以将项目视为重量并选择一个随机值并将其与重量进行比较。遍历列表并从随机值中减去权重,直到它小于列表概率。在使用该项目的下一次迭代中,概率会发生变化,直到它为空。

   x = random([0.0, 1.0])
   for i in 0..n
       if x < probabilities[i]
        choose(i)
         break
       else
         x -= probabilities[i]
     end
    end
于 2013-07-29T23:19:03.717 回答
-1

你可以试试这样的。假设您有一个像您提到的那样的数组,其中数据来自数据库:

red   => 100
green => 200
blue  =>  50

添加所有组合颜色的值(在本例中为 350)。选择一个介于 1 和那个之间的随机值。

$randValue = rand(1, 350);

然后使用循环逐步减去颜色的值,直到剩下 0 或负数:

foreach ($colors as $key => $value) {
    $randValue = $randValue - $value;
    if ($randValue < 1) {
        $pickedColor = $key;
        // and substract 1 from this color in the DB
        break;
    }
}

所以,在这种情况下,如果$randValue是 124,你会得到绿色。

于 2013-07-29T23:18:52.500 回答