生成指定暂停的列表

2024-04-26 18:58:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两个号码:

amount = 100
seconds = 30000

我想创建一个100($amount)个暂停的列表,它们的总和是30000($seconds)。你知道吗

而且停顿必须是5到1000之间的数字。你知道吗

换句话说,我们必须把30000分成100个随机部分,但在5到1000之间。你知道吗

我怎么做到的?你知道吗


Tags: 列表数字amount号码seconds总和
3条回答

我没有把我的努力放在这个问题上,因为我有一些想法,但想看到完全不同的观点对这个问题。 在你的回答之后,我重新考虑了我的计划,写了这样一段话:

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)

实际上,它留给我们的暂停时间不到$秒,但对我来说,它是完美的。你知道吗

一个简单的方法是从均匀分布开始,然后随机选取两个指数,并将一个以最小值和最大值为上限的随机量从一个指数移动到另一个指数。这样做一定次数,序列应该足够随机,同时保留所有约束。你知道吗

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]

为了简单起见,这假设n可以被k平均整除,但即使不是,第一步也很容易适应。你知道吗

这不是一个最佳的解决方案,更多的是一个草图,因为我的时间紧迫,但它似乎工作:

首先,创建一个从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]

编辑:注意,这将导致所有的间隔变得大致相等,因为您是统一选择的。我想你可以把采样的方式改成高斯分布在时间轴的中间。然后你可以调整停顿,这样短的停顿就不会总是在开头和结尾。你知道吗

相关问题 更多 >