Подтвердить что ты не робот

Может ли Python генерировать случайное число, исключающее набор чисел без использования рекурсии?

Я просмотрел Python Docs (возможно, я неправильно понял), но я не видел, чтобы был способ сделать это (посмотрите ниже) без вызова рекурсивной функции. Я хотел бы создать случайное значение, которое исключает значения в середине.

Иными словами,
Предположим, я хотел, чтобы X был случайным числом, которое не было в range(a - b, a + b)
Могу ли я сделать это на первом проходе,
или
1. Должен ли я постоянно генерировать число,
2. Проверьте, есть ли в range(),
3. Промыть ополаскиватель?

Что касается того, почему я не хочу писать рекурсивную функцию,  1. "чувствует", что мне не нужно  2. набор чисел, которые я делаю для этого, может на самом деле оказаться довольно большим, и
... Я слышал, что переполнение стека плохое, и я могу быть слишком осторожным в этом.

Я уверен, что есть хороший, Pythonic, нерекурсивный способ сделать это.

4b9b3361

Ответ 1

Используйте random.choice(). В этом примере a - ваша нижняя граница, пробег между b и c пропущен, а d - верхняя граница.

import random
numbers = range(a,b) + range(c,d)
r = random.choice(numbers)

Ответ 2

Создайте одно случайное число и нарисуйте его на нужные диапазоны чисел.

Если вы хотите сгенерировать целое число между 1-4 или 7-10, за исключением 5 и 6, вы можете:

  • Генерировать случайное целое число в диапазоне 1-8
  • Если случайное число больше 4, добавьте 2 к результату.

Отображение будет:

Random number:    1  2  3  4  5  6  7  8
Result:           1  2  3  4  7  8  9 10

Выполняя это так, вам никогда не нужно "перематывать". Вышеприведенный пример предназначен для целых чисел, но он также может применяться к поплавкам.

Ответ 3

Возможным решением было бы просто сдвинуть случайные числа из этого диапазона. Например.

def NormalWORange(a, b, sigma):
    r = random.normalvariate(a,sigma)
    if r < a:
        return r-b
    else:
        return r+b

Это создало бы нормальное распределение с отверстием в диапазоне (a-b, a + b).

Изменить: если вам нужны целые числа, вам понадобится немного больше работы. Если вам нужны целые числа, находящиеся в диапазоне [c, a-b] или [a + b, d], то следующее должно сделать трюк.

def RangeWORange(a, b, c, d):
    r = random.randrange(c,d-2*b) # 2*b because two intervals of length b to exclude
    if r >= a-b:
        return r+2*b
    else:
        return r

Ответ 4

Возможно, я неправильно понял вашу проблему, но вы можете реализовать это без рекурсии

def rand(exclude):
    r = None
    while r in exclude or r is None:
         r = random.randrange(1,10)
    return r

rand([1,3,9])

хотя вы все еще просматриваете результаты, пока не найдете новые.

Ответ 5

Самое быстрое решение будет таким: (a и b определяют зону исключения, а c и d - набор хороших ответов, включая зону исключения):

offset = b - a
maximum = d - offset
result = random.randrange(c, maximum)
if result >= a:
    result += offset

Ответ 6

Вам по-прежнему нужен некоторый диапазон, т.е. возможное значение min-max, исключая ваши средние значения.

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

def rand_not_in_range(a,b):
    rangechoices = ((0,a-b-1),(a+b+1, 10000000))
    # Pick a half
    fromrange = random.choice(rangechoices)
    # return int from that range
    return random.randint(*fromrange)

Ответ 7

Li-Аун Yip ответ делает выпуск рекурсии спорным, но я должен отметить, что это возможно сделать любую степень рекурсии, не заботясь о стеке. Это называется "хвостовая рекурсия". Python не поддерживает хвостовую рекурсию напрямую, потому что GvR думает, что это uncool:

http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html

Но вы можете обойти это:

http://paulbutler.org/archives/tail-recursion-in-python/

Мне интересно, что палка считает, что рекурсия "чувствует себя не так". В чрезвычайно функционально-ориентированных языках, таких как Scheme, рекурсия неизбежна. Он позволяет выполнять итерацию без создания переменных состояния, которые парадигма функционального программирования строго избегает.

http://www.pling.org.uk/cs/pop.html