均匀大小的桶之间的随机分布,无需重复

时间:2012-06-04 17:35:07

标签: algorithm math distribution probability

问题

我将各种类型的N个项目均匀地分配到由类型确定的自己的桶中。我想创建一个新列表:

  1. 从每个桶中随机挑选
  2. 连续两次从同一个桶中挑选
  3. 每个桶必须(如果可能)在最终列表中具有相同数量的表示
  4. 不使用特定于语言的库(不易用其他语言实现)
  5. 实施例

    我有12个4种不同类型的项目,这意味着我有4个桶:

    Bucket A - [a, a, a]
    Bucket B - [b, b, b]
    Bucket C - [c, c, c]
    Bucket D - [d, d, d]
    

    我想要什么

    随机分布中的上述项目列表,其中没有任何字符重复,大小介于1和N之间。

    12 Items: a, d, c, a, b, a, c, d, c, b, d, b
    
    8 Items: c, a, d, a, b, d, c, b
    
    4 Items: c, b, d, a
    
    3 Items: b, c, a (Skipping D)
    

    我试图使用while循环生成随机整数,直到下一个存储桶不等于之前使用的存储桶,但这似乎效率低下,并希望其他人可能有更好的算法来解决此问题

2 个答案:

答案 0 :(得分:1)

您可以生成随机的存储桶列表,然后按顺序从中随机选择,从中挑选时从列表中删除存储桶。当列表为空时,重新生成一个桶的随机列表,重复直到您选择所需数量的项目。

你能从桶中重复一下吗?因此,如果您第一次从水桶A中选择第一个“a”,您可以第二次选择吗?这将改变解决方案。

答案 1 :(得分:1)

已编辑以响应每个存储桶中不必连续绘制的约束。抛弃不符合标准的排列很简单。现在,如果两个桶具有相同的“标签”,则会失败(原样)。

使用itertoolsrandom.sample进行排列的小黑客:

import random
import itertools as itr
from math import ceil

def buckets_choice(N,labels):
    items = int(ceil(float(N)/len(labels)))
    b = list(itr.chain(*(labels for _ in xrange(items))))

    while True:
        p = random.sample(b,len(b))
        cond = map( (lambda x,y: x==y), p[1:], p[:1])
        if not sum(cond):  return p[:N]

L = ['a','b','c','d']
for _ in xrange(5):
    print buckets_choice(3,L), buckets_choice(8,L), buckets_choice(12,L)

示例运行给出(为清晰起见,删除了引号):

(a, b, d) (b, d, c, a, d, a, b, c) (b, c, d, c, d, a, d, b, a, c, b, a)
(b, a, d) (d, a, c, c, a, b, b, d) (c, b, a, b, a, c, b, d, d, a, d, c)
(b, d, a) (b, c, c, a, b, a, d, d) (a, d, a, d, c, b, d, c, a, b, c, b)
(d, c, b) (c, d, a, b, c, b, a, d) (c, b, a, a, b, c, d, c, b, a, d, d)
(b, d, a) (c, b, b, d, c, a, d, a) (c, b, d, a, d, b, b, d, c, a, a, c)