生成指定的暂停列表

时间:2018-12-18 20:36:10

标签: python list

我有2个数字:

amount = 100
seconds = 30000

我想创建一个包含100个($amount)暂停的列表,所有这些暂停之和为30000 ($seconds)

而且暂停时间必须介于5到1000之间。

换句话说,我们必须将30000分为100个随机部分,但介于5和1000之间。

我该怎么做?

3 个答案:

答案 0 :(得分:0)

这不是最佳解决方案,更多的是草图,因为我时间紧迫,但这似乎可行:

首先,创建一个从0到seconds的数组,就像时间轴一样。

timeline = np.arange(0, seconds+1)

现在将其拆分为min_length = 5等距的块

chunks = []
for ii in range(0, seconds, 5):
    chunks.append(timeline[ii:ii+5])

现在,我们的想法是在chunks中选择一个随机元素,合并以下2个元素,然后将其随机分为2个块​​(因此将3个块减少为2个)。但是,我们必须以一种方式进行处理,以免将其分割成大小小于min_length= 5但不大于max_length=1000的块。然后,我们将对此进行循环,直到获得所需的块数,即amount=100

def random_merge(chunks, min_length, max_length):
    arr = chunks.copy() # just to be safe

    # Choose random point
    rand_idx = random.randint(0, len(arr)-3)

    # Combine merge with the following 2 elements
    arr[rand_idx] = np.append(arr[rand_idx], arr[rand_idx + 1])
    arr[rand_idx] = np.append(arr[rand_idx], arr.pop(rand_idx + 2))

    # choose a random length to split into smaller chunks such that neither
    # smaller chunk has a length less than min_length
    rand_split = random.randint(min_length, len(arr[rand_idx]) - min_length)
    arr[rand_idx+1] = arr[rand_idx][rand_split:]
    arr[rand_idx] = arr[rand_idx][:rand_split]

    # check to see if the split made an element with length greater than
    # max_length if not return your new smaller array, if not just return the
    # original array and start over
    if len(arr[rand_idx] < max_length) and len(arr[rand_idx+1] < max_length):
        return arr
    else:
        return chunks

现在,只需循环遍历,直到达到所需的块数即可:

while len(chunks) > amount:
    chunks = random_merge(chunks)

这将为您提供分区的时间线,以获取持续时间,只需测量其长度即可

pauses = [len(xx) for xx in chunks]

编辑:请注意,这将导致所有间隔变得大致相等,因为您要进行统一选择。我认为您可以将rand_idx的采样方式更改为类似以时间轴为中心的高斯的方式。然后,您可以将停顿点改编,这样短的停顿点就不会总是在开头和结尾。

答案 1 :(得分:0)

一种简单的方法是从均匀分布开始,然后随机选择两个索引,然后将一个由最小值和最大值限制的随机量从一个移到另一个。这样做一定次数,并且序列应该足够随机,同时保留所有约束。

from random import randint, randrange
n, k = 30000, 100
mn, mx = 5, 1000
nums = [n//k for _ in range(k)]

for _ in range(10000):
    a, b = randrange(k), randrange(k)
    swap = randint(0, min(mx - nums[a], nums[b] - mn))
    nums[a] += swap
    nums[b] -= swap

print(min(nums), max(nums), sum(nums))
# 5 1000 30000
print(nums)
# [9, 773, 65, 812, 23, 124, 396, 406, 51, 241, 241, 841, 274, 210, 28, 213, 550, 131, 243, 974, 194, 927, 174, 910, 121, 230, 22, 7, 22, 128, 404, 247, 276, 8, 118, 68, 5, 216, 45, 10, 43, 32, 723, 56, 398, 12, 861, 625, 200, 755, 6, 563, 77, 279, 424, 6, 523, 15, 540, 858, 925, 491, 21, 499, 984, 21, 397, 18, 219, 83, 5, 171, 588, 159, 126, 796, 5, 68, 62, 12, 169, 849, 96, 426, 637, 127, 44, 497, 237, 597, 447, 19, 12, 267, 85, 78, 112, 471, 447, 1000]

为简单起见,这里假设nk整除,但是即使不是,第一步也很容易适应。

答案 2 :(得分:0)

我没有在这个问题上全力以赴,因为我有一个主意但是想对这个问题有完全不同的看法。 在您回答之后,我重新考虑了我的计划并写成这样:

import random

amount = 100
seconds = 30000

numbers = list(range(0,1001))
print(numbers)

pauses = []
i=0
while i < amount:
    rand_idx = random.randint(0, len(numbers)-1)
    pauses.append(numbers[rand_idx])
    i+=1

pausetime = sum(pauses)


if pausetime > seconds:
    while pausetime > seconds:
        max_idx = pauses.index(max(pauses))      # check index of highest pause
        half_rand_idx = random.randint(0, (len(numbers)-1)/2)
        pauses[max_idx] = numbers[half_rand_idx] # change highest pause for other random pause from first half
        pausetime = sum(pauses)          # check the sum of all pauses

elif pausetime < seconds:
    while pausetime < seconds:
        max_idx = pauses.index(min(pauses)) # check index of lowest pause
        pauses[min_idx] = numbers[rand_idx] # change highest pause for other random pause
        pausetime = sum(pauses)         # check the sum of all pauses

else:
    pass

print(pauses)
print(pausetime)

它实际上使我们的暂停时间少于$ seconds,但就我而言,这是完美的。