Question: I'm trying to generate (pseudo)random numbers using the random module. I need the numbers generated to not be too close to each other in terms of range. For example, if a number of n is generated, then another number x cannot be n +- 5.

```
from random import randint

i = 10

j_list = []
k_list = []

while i != 0:

    j = randint(-10, 10)
    k = randint(-15, 15)

    j_list.append(j)
    k_list.append(k)

    i -= 1

print("J list is: {} and K list is {}".format(j_list, k_list))

```

For example, when I ran it last time, I got following output:

```
J list is: [-4, 5, 2, -3, 7, -4, 3, -1, -1, -6] and K list is [10, 3, -7, -1, -5, -11, 3, 8, 1, -7]

```

As you can see, the 1st and 3rd elements of j\_list (that is, j\_list[1:3]) are within +- 5 of one another. This is not something I want; I want every element in the list to produce values that are out of certain range.

Is there any way of doing this?

Answer: 
First of all, using a for loop is better than using a while loop here:

```
# One line and you know the loop range immediately
for i in range(10):
    print(i)

# Three lines and takes the reader two seconds to comprehend
i = 10
while i != 0:
    i -= 1
    print(i)

```

Now to answer your question, you can use random.choice to exclude range(j - 5, j + 5):

```
from random import randint, choice

j_list = []
k_list = []

for i in range(10):

    j = randint(-10, 10)
    k = choice([n for n in range(-15, 15) if n not in range(j - 5, j + 6)])

    j_list.append(j)
    k_list.append(k)

print("J list is: {} and K list is {}".format(j_list, k_list))

```

If you only want to use randint, an alternative is to use a while loop to keep rerolling value k until it does not fall in the j +- 5 range:

```
from random import randint

j_list = []
k_list = []

for i in range(10):

    j = randint(-10, 10)
    k = randint(-15, 15)

    while abs(j - k) <= 5:

        k = randint(-15, 15)

    j_list.append(j)
    k_list.append(k)

print("J list is: {} and K list is {}".format(j_list, k_list))

```

As @ShadowRanger points out, the while loop strategy is less computational demanding and is easier to read so you might want to go for that.
The best solution here is not to filter out bad values, but to prevent them from ever occurring in the first place. An easy solution is to generate a more restrictive range of numbers (as large as the overall bounds, minus the numbers to exclude), then add the size of the omitted numbers to the result if the result is equal to or greater than the bottom of the excluded range.

```
from random import randint

i = 10

j_list = []
k_list = []

too_close = 5    

while i != 0:

    j = randint(-10, 10)
    k = randint(-15, 15 - (too_close * 2 + 1))  # excluding j +- 5 means 11 numbers we won't use
    # The range from j - 5 to 4 is logically j + 6 to 15, so when we
    # generate a number of j - 5 or higher, we add 11 to adjust it to the desired result
    if k >= j - too_close:
        k += too_close * 2 + 1

    j_list.append(j)
    k_list.append(k)

    i -= 1

print("J list is: {} and K list is {}".format(j_list, k_list))

```

This should win on performance for a PRNG of any complexity, since it means you never generate *any* additional random numbers; there is no "test for bad and generate new loop" or the like, because you make sure you've generate valid numbers directly.

Side-note:

```
i = 10
while i != 0:
    ...
    i -= 1

```

where `i` is otherwise unused is a pointlessly complicated way to spell:

```
for i in range(10):
    ...

```

Or if i must descend from 10 to 0:

```
for i in range(10, 0, -1):
    ...

```

Either `for` will outperform the `while`, and be significantly less error prone (can't forget to adjust `i` or skip the adjust step via `continue` or the like).