我有2个数字:
amount = 100
seconds = 30000
我想创建一个包含100个($amount)
暂停的列表,所有这些暂停之和为30000 ($seconds)
。
而且暂停时间必须介于5到1000之间。
换句话说,我们必须将30000分为100个随机部分,但介于5和1000之间。
我该怎么做?
答案 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]
为简单起见,这里假设n
被k
整除,但是即使不是,第一步也很容易适应。
答案 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,但就我而言,这是完美的。