Estoy tratando de generar (pseudo) números aleatorios usando el módulo aleatorio. Necesito que los números generados no sean demasiado cercanos entre sí en términos de rango. Por ejemplo, si se genera un número de n, entonces otro número x no puede ser 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))

Por ejemplo, cuando lo ejecuté la última vez, obtuve el siguiente resultado:

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]

Como puede ver, los elementos primero y tercero de j_list (es decir, j_list [1: 3]) están dentro de + - 5 entre sí. Esto no es algo que quiero; Quiero que cada elemento de la lista produzca valores que estén fuera de cierto rango.

¿Hay alguna forma de hacer esto?

1
korean_kiwi 14 sep. 2018 a las 04:51

3 respuestas

La mejor respuesta

En primer lugar, usar un bucle for es mejor que usar un bucle while aquí:

# 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)

Ahora para responder a su pregunta, puede usar random.choice para excluir el rango (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))

Si solo desea usar randint, una alternativa es usar un ciclo while para seguir rebobinando el valor k hasta que no caiga en el rango j + - 5:

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))

Como señala @ShadowRanger, la estrategia del bucle while es menos exigente desde el punto de vista computacional y es más fácil de leer, por lo que es posible que desee hacerlo.

2
Victor Wong 14 sep. 2018 a las 02:28

¿Qué tal algo en este sentido? Esto puede alterar fácilmente la cantidad de iterations, el rango de su randint y el espacio permitido entre su randint

from random import randint

def not_within_five(lista):
    i = 0
    while i < 10:
        x = randint(0, 50) 
        if lista[i] in range(x-5, x+5):
            continue
        else:
            lista.append(x)
            i += 1

j = []
k = []

j.append(randint(0, 50))
k.append(randint(0, 50))

not_within_five(j)
not_within_five(k)

print(f"J list is {j}\n")
print(f"K list is {k}")

Salida

(xenial)vash@localhost:~/python$ python3.7 randi.py
J list is [19, 31, 49, 3, 9, 42, 29, 41, 22, 0, 35]

K list is [42, 19, 13, 27, 42, 1, 26, 10, 17, 40, 47]
-1
vash_the_stampede 14 sep. 2018 a las 02:46

La mejor solución aquí no es filtrar los valores incorrectos, sino evitar que ocurran en primer lugar. Una solución fácil es generar un rango de números más restrictivo (tan grande como los límites generales, menos los números a excluir), luego agregar el tamaño de los números omitidos al resultado si el resultado es igual o mayor que la parte inferior de El rango excluido.

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))

Esto debería ganar en el rendimiento para un PRNG de cualquier complejidad, ya que significa que nunca generará any números aleatorios adicionales; no hay "prueba de mal y generar nuevo bucle" o similar, porque se asegura de haber generado números válidos directamente.

Nota al margen:

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

Donde i no se utiliza de otra manera es una forma de deletrear innecesariamente complicada:

for i in range(10):
    ...

O si debo descender de 10 a 0:

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

Cualquiera de for superará al while y será significativamente menos propenso a errores (no se puede olvidar ajustar i u omitir el paso de ajuste a través de continue o similar).

0
ShadowRanger 14 sep. 2018 a las 02:18