web-dev-qa-db-ja.com

Python再帰を使用せずに、一連の数値を除外する乱数を生成できますか?

私は Python Docs (誤解しているかもしれません)を見ましたが、再帰関数を呼び出さずにこれを行う方法(以下を参照)があることはわかりませんでした。
私がしたいことは、真ん中の値を除外するランダムな値を生成することです。

言い換えると、
私がXに含まれていない乱数にしたいと想像してみましょう
range(a - b, a + b)
これを最初のパスで実行できますか、
または
1。常に番号を生成する必要がありますか、
2。 range()かどうかを確認します。
3。リンスを洗う?

再帰関数を書きたくない理由は、
1。それは私がする必要はないはずの「のように感じる」
2。私がこれを行っている数のセットは、実際にはかなり大きくなる可能性があり、
...スタックオーバーフローが悪いと聞きましたが、これを行うことに過度に注意しているだけかもしれません。

私はそれを行うための素晴らしい、Pythonic、非再帰的な方法があると確信しています。

31
user890167

Random.choice()を使用します。この例では、aは下限、bとcの間の範囲はスキップされ、dは上限です。

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

1つの乱数を生成し、それを目的の数値範囲にマッピングします。

1-47-10を除いて、5または6の整数を生成する場合は、次のようにします。

  1. 1-8の範囲でランダムな整数を生成します
  2. 乱数が4より大きい場合は、結果に2を追加します。

マッピングは次のようになります。

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

このようにすると、「再ロール」する必要がなくなります。上記の例は整数の場合ですが、浮動小数点にも適用できます。

41
Li-aung Yip

可能な解決策は、乱数をその範囲外にシフトすることです。例えば。

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
9
Ken

私はあなたの問題を誤解したかもしれませんが、再帰せずにこれを実装できます

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

Rand([1,3,9])

ただし、新しい結果が見つかるまで、結果を繰り返し処理しています。

7
zmo

最速のソリューションは次のようになります(aとbで除外ゾーンを定義し、cとdで除外ゾーンを含む適切な回答のセットを使用します)。

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

Li-aung Yipの答えは再帰の問題を解決しますが、スタックを気にせずに任意の程度の再帰を実行できることを指摘しなければなりません。これは「末尾再帰」と呼ばれます。 Pythonは、GvRがクールではないと考えるため、末尾再帰を直接サポートしていません。

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

0

それでもsomeの範囲、つまり、中間の値を除いた最小-最大の可能な値が必要です。

まず、範囲の「半分」をランダムに選んでから、その範囲の乱数を選んでみませんか?例えば。:

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)
0
Francis Avila