After I sort a randomly generated list, I have consecutive numbers, eg
[7, 9, 13, 47, 64, 76, 83, 94, 95, 114, 115, 116, 120, 121, 123, 124, 127, 136, 152, 154, 167, 184, 189, 205, 212, 222, 226, 229, 231, 238]
Here consecutive numbers are (94, 95)
, (120, 121)
and (123, 124)
. How do I remove them?
My code is:
while len(set(l)) != 30:
a = random.randint(1, 240)
l.append(a)
l = list(set(l))
l = sorted(l)
f.write(str(l))
I do not want to use randrange
or choice
from random
module.
Create a random number a
and check if a
and a±1
are not in the set:
import random
l = set()
while len(l) != 30:
a = random.randint(1, 240)
if not {a-1,a,a+1} & l: # set intersection: empty == False == no common numbers
l.add(a)
l = sorted(l) # sorted creates a sorted list from any iterable
print(l)
Output:
[5, 12, 40, 47, 55, 59, 62, 73, 76, 82, 84, 89, 93, 95, 109,
125, 127, 141, 165, 168, 184, 187, 196, 202, 204, 210, 215,
218, 229, 231]
Directly using a set makes the check if the number (±1) is already part of your random numbers very fast.
Doku:
And as function:
import random
def get_random_numbers_no_neighboring_elems(min_num, max_num, amount):
"""Generates amount random numbers in [min_num,..,max_num] that do not
include neighboring numbers."""
# this is far from exact - it is best to have about 5+ times the amount
# of numbers to choose from - if the margin is too small you might take
# very long to get all your "fitting numbers" as only about 1/4 of the range
# is a viable candidate (worst case):
# [1 2 3 4 5 6 7 8 9 10]: draw 2 then 5 then 8 and no more are possible
if (max_num-min_num) // 5 < amount:
raise ValueError(f"Range too small - increase given range.")
l = set()
while len(l) != amount:
a = random.randint(min_num, max_num)
if not {a-1,a,a+1} & l: # set intersection: empty == False == no commons
l.add(a)
return sorted(l)
print(get_random_numbers_no_neighboring_elems(1,240,80))
I add a solution where edges can be selected with same probability than others, but they need to be mutually exclusive :
def rand2(k,n,edge=False):
forbid=set()
l=set()
while len(l)<k:
x=random.randint(1,n)
if x not in forbid :
l.add(x)
forbid.update({x,x-1,x+1})
if edge and x in {1,n} : forbid.add(n+1-x)
return l
from collections import Counter
print(Counter([tuple(rand2(2,5)) for i in range(10000)]))
#Counter({(2, 4):1943, (1, 4):1720, (3, 5):1711, (2, 5):1652, (1, 3):1637, (1, 5):1337})
print(Counter([tuple(rand2(2,5,edge=True)) for i in range(100000)]))
#Counter({(2, 5): 2060, (3, 5): 2026, (1, 4): 1981, (1, 3): 1975, (2, 4): 1958})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.