Создайте список указанных пауз - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть 2 числа:

amount = 100
seconds = 30000

Я хочу создать список из 100 ($amount) пауз, сумма которых составляет 30000 ($seconds).

Итакже паузы должны быть числом от 5 до 1000.

Другими словами, мы должны разделить 30000 на 100 случайных частей, но между 5 и 1000.

Как мне это сделать?

Ответы [ 3 ]

0 голосов
/ 19 декабря 2018

Простым способом было бы начать с равномерного распределения, а затем случайным образом выбрать два индекса и переместить случайное количество, ограниченное минимальным и максимальным значениями, от одного к другому.Сделайте это определенное количество раз, и последовательность должна быть достаточно случайной при сохранении всех ограничений.

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 голосов
/ 19 декабря 2018

Я не прикладывал усилий к этому вопросу, потому что у меня была некоторая идея, но я хотел увидеть совершенно другой взгляд на проблему.После ваших ответов я пересмотрел свой план и написал следующее:

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)

это фактически оставляет нам паузу чуть меньше, чем $ секунд, но для моего случая это идеально.

0 голосов
/ 19 декабря 2018

Это не оптимальное решение, скорее набросок, так как мне не хватает времени, но, похоже, оно работает:

Сначала создайте массив от 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 на что-то вроде гауссиана с центром в середине временной шкалы.Затем вы можете перетасовать паузы, чтобы короткие не всегда были в начале и в конце.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...