I have a script that generates a randomised list of numbers between 0,60 and it is sorted in ascending order.
Essentially, I want to check if the difference between each element, and the element next to it is above 3, and if it is not, I want the list to be regenerated until the condition applies.
For example:
my_list = [1, 2, 3, 4, 5]
# this would not pass
my_list = [1, 5, 9, 13, 20]
# this would pass as the difference between each element and the next is more than 3
My code so far:
def generateList():
timeSlots = list(range(0, 60)) # generate random list
random.shuffle(timeSlots) # shuffle list
timeSlots = timeSlots[:9] # shorten list to 9 elements
timeSlots.sort() # sort list in ascending order
for cur, nxt in zip(timeSlots, timeSlots[1:]):
diff = (nxt - cur) # check difference
if diff < 3:
# HELP HERE
# regenerate timeSlots until the sum of each element and the next element is bigger than 3
return timeSlots
CodePudding user response:
You want to use all()
:
def generateList():
while True:
timeSlots = list(range(0, 60)) # generate random list
random.shuffle(timeSlots) # shuffle list
timeSlots = timeSlots[:9] # shorten list to 9 elements
timeSlots.sort() # sort list in ascending order
if all(nxt - cur > 3 for cur, nxt in zip(timeSlots, timeSlots[1:])):
return timeSlots
Note, if you want to select only 9 elements, then you can use randome.sample()
.
import random
def generate_list():
while True:
time_slots = random.sample(range(60), 9) # note this will not include 60 in the population
time_slots.sort() # sort list in ascending order
# or combine the above 2 lines as
# time_slots = sorted(random.sample(range(60), 9))
if all(nxt - cur > 3 for cur, nxt in zip(time_slots, time_slots[1:])):
return time_slots
CodePudding user response:
You can just perform a recursive call if your list does not match your criteria. This add a single line to your program:
import random
def generateList():
timeSlots = list(range(0, 60))
random.shuffle(timeSlots)
timeSlots = timeSlots[:9]
timeSlots.sort()
for cur, nxt in zip(timeSlots, timeSlots[1:]):
diff = (nxt - cur)
if diff < 3:
return generateList() # does not work => try a new one
return timeSlots
generateList()
CodePudding user response:
import random
def generateList():
while True:
timeSlots = list(range(0, 60)) # generate random list
random.shuffle(timeSlots) # shuffle list
timeSlots = timeSlots[:9] # shorten list to 9 elements
timeSlots.sort() # sort list in ascending order
for cur, nxt in zip(timeSlots, timeSlots[1:]):
diff = (nxt - cur) # check difference
if diff < 3:
break
else:
return timeSlots
print(generateList())
CodePudding user response:
I want to check if the difference between each element, and the element next to it is above 3, and if it is not, I want the list to be regenerated until the condition applies.
Answers have already shown how to check the list, but depending on your numbers, the chances for generating a valid list of that kind might be very low, or there might not be a valid list at all. In this case, your loop would run a long time, or infinitely.
Instead, you can just generate a valid list. Let's say the K=10
elements must be smaller than N=60
with a difference greater than M=3
. Then you know that M*(K-1)
has to be "reserved" for the gaps, and you can random.sample
numbers from the rest, then apply the accumulated gaps afterwards.
import random
N, M, K = 60, 3, 10
nums = sorted(random.sample(range(N - (K-1)*M), K))
# [2, 5, 13, 16, 21, 23, 27, 28, 31, 32] (random)
res = [x i*M for i, x in enumerate(nums)]
# [2, 8, 19, 25, 33, 38, 45, 49, 55, 59] (random)
As a side effect, this will immediately raise an exception if there is no such list.
Thus, your generateList
function could look like this, without loops:
def generateList(n=60, m=3, k=10):
nums = sorted(random.sample(range(n - (k-1)*m), k))
return [x i*m for i, x in enumerate(nums)]