Python 使用规则随机生成列表元素

Python 使用规则随机生成列表元素,python,algorithm,Python,Algorithm,让列表l由n个元素组成,其中 每个元素应为0或小于或等于r的正整数,并且 列表的总和应等于m 例如: Given n = 5, r = 4, m = 10 l = [4, 3, 2, 0, 1] 实现规则(1)很容易,但我想知道是否有什么好主意/算法来实现这两个规则?合理的解释是:(I)找到并计算所有满足规则的唯一列表;以及(ii)以相同的概率随机选择这些列表中的一个。这种方法的问题是对列表进行编码很复杂 一种更简单的方法(更少的代码)是将每个正确的列表暴露在相同的被选中概率下。该算法是:

让列表l由n个元素组成,其中

  • 每个元素应为0或小于或等于r的正整数,并且
  • 列表的总和应等于m
  • 例如:

    Given n = 5, r = 4, m = 10
    
    l = [4, 3, 2, 0, 1]
    

    实现规则(1)很容易,但我想知道是否有什么好主意/算法来实现这两个规则?

    合理的解释是:(I)找到并计算所有满足规则的唯一列表;以及(ii)以相同的概率随机选择这些列表中的一个。这种方法的问题是对列表进行编码很复杂

    一种更简单的方法(更少的代码)是将每个正确的列表暴露在相同的被选中概率下。该算法是:


  • 检查
    m这里有一个简单的暴力解决方案。基本上,您希望生成样本,其中小于
    r
    的随机整数的可能性相同。不符合标准(总和为
    m
    )的样本将被拒绝

    import numpy as np
    
    def rand_with_rules(n, r, m):
        if n*(r-1) < m:
            raise ValueError
        while True:
            l = np.random.randint(0, r, size=(n))
            if l.sum() == m:
                return l
    
    将numpy导入为np
    定义带有规则的随机数(n,r,m):
    如果n*(r-1)
    请注意,拒绝样品必然会使您的“随机”数字产生偏差。由于您的限制,您不能拥有一组纯粹的随机和确定的数据,这些数据往往会过多或不足

    以n,r,m=2,3,4为例。唯一符合此标准的序列是(2,2),因此绘制2的可能性为100%,其他值为0%

    本质上,此解决方案声明您事先不知道哪些整数最有可能。然而,通过这些限制,你对数字的后验知识几乎永远不会真正统一


    对于给定此约束的整数分布,可能有一个聪明的分析解决方案,您可以使用它生成样本。但我不知道那是什么

    如果不验证所有规则可以同时满足,我建议以下解决方案

    import random
    
    def dis(n,m,r):
      l = [0] * n
    
      for inc in range(1,m):
        l.sort()
        for ind_less_r, less_r in enumerate(l):
          if less_r > r:
              break
        l[random.randint(0,ind_less_r-1)] += 1
    
      random.shuffle(l)
      return l
    
    
    for i in range(1,10):
      print dis(10,50,9)
    
    结果是

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

    由于您在评论中回答说它可以有许多0,并且数字可以重复,所以我推断它不需要那么随机。考虑到这一点,这里是一个没有任何循环或包含的基本解决方案。它假定
    n
    r
    m
    具有有效的值和类型。但这样的检查很简单,可以添加,我会根据要求编辑它们

    def create_list(n, r, m):
        output = [r] * (m/r)
        remainder = m - r * len(output)
        if remainder != 0:
            output += [m - r * len(output)]
        output += [0] * (n - len(output))
        return output
    
    output = create_list(5, 4, 10) # gives [4, 4, 2, 0, 0]
    output = create_list(5, 2, 10) # gives [2, 2, 2, 2, 2]
    

    p.S.-请求的值小于
    r
    ,但示例显示的值等于
    r
    ,因此这是示例

    如果条件不满足(例如,n=5,r=4,m=100),您打算怎么办?我只想指出,如果添加定义如何生成列表的规则,列表将不再是随机的。是否需要一定数量的0?或者元素是独一无二的?否则,只要
    rm
    ,我就只使用
    r
    floor(m/r)
    次,然后插入一个余数,然后用0填充,直到
    n
    满意为止。它应该是多少随机数?请原谅我问显而易见的问题,但结果必须只包含正整数吗?我的答案不正确!我根本不应该用多项式。我正试图找到正确的方法。pymc不是实现了多项式只支持一个选定的和吗?我想我明白了,这里的问题是你不能保证某个类别(数组元素)的“成功”数量受到韩国的限制,我去掉了pymc和多项式分布的部分,我认为这是正确的。这个解决方案既愚蠢又刻薄,肯定无法扩展,但对于海报来说可能已经足够好了。OP说他只想要小于
    r
    。我认为最初的问题要求的值仅小于
    r
    。除此之外,这看起来不错!是的,我修好了。谢谢你的注意。
    [7, 7, 6, 1, 6, 3, 5, 4, 4, 6]
    [5, 6, 7, 5, 4, 7, 4, 4, 4, 3]
    [4, 3, 2, 4, 7, 7, 5, 7, 5, 5]
    [4, 4, 5, 6, 4, 6, 6, 4, 5, 5]
    [6, 6, 4, 6, 5, 6, 2, 5, 4, 5]
    [2, 8, 4, 2, 6, 5, 4, 4, 6, 8]
    [6, 6, 3, 4, 5, 5, 5, 5, 6, 4]
    [6, 4, 5, 6, 7, 3, 1, 5, 6, 6]
    [4, 5, 4, 7, 6, 6, 3, 2, 6, 6]
    
    def create_list(n, r, m):
        output = [r] * (m/r)
        remainder = m - r * len(output)
        if remainder != 0:
            output += [m - r * len(output)]
        output += [0] * (n - len(output))
        return output
    
    output = create_list(5, 4, 10) # gives [4, 4, 2, 0, 0]
    output = create_list(5, 2, 10) # gives [2, 2, 2, 2, 2]