は、ソリューションのカップルです。
最初のアルゴリズムでは、シーケンスにインデックスidx
が保持され、各コールでidx
がランダムに異なるインデックスに変更されるため、生成された値が以前の値と等しくなることはありません。
from random import randrange
from itertools import islice
from collections import Counter
def non_repeating(seq):
m = len(seq)
idx = randrange(0, m)
while True:
yield seq[idx]
idx = (idx + randrange(1, m)) % m
seq = [1, 2, 3, 4]
print(''.join(map(str, islice(non_repeating(seq), 60))))
ctr = Counter(islice(non_repeating(seq), 12000))
print(ctr)
典型的な出力
313231412323431321312312131413242424121414314243432414241413
Counter({1: 3017, 4: 3012, 3: 2993, 2: 2978})
そのコードによって生成された値の分布はかなり均一に見えるが、私は数学的にそれを解析していない、と私はその均一性について何らの保証を行いません。
次のコードはより複雑ですが、一様な分布になっています。反復された値は破棄されず、繰り返し値のプールに一時的に追加され、アルゴリズムはできるだけ早くプール内の値を使用しようとします。プール内で適切な値が見つからない場合は、新しいランダム値を生成します。
from random import choice
from itertools import islice
from collections import Counter
def non_repeating(seq):
pool = []
prev = None
while True:
p = set(pool).difference([prev])
if p:
current = p.pop()
pool.remove(current)
else:
current = choice(seq)
if current == prev:
pool.append(current)
continue
yield current
prev = current
seq = [1, 2, 3, 4]
print(''.join(map(str, islice(non_repeating(seq), 60))))
ctr = Counter(islice(non_repeating(seq), 12000))
print(ctr)
142134314121212124343242324143123212323414131323434212124232
Counter({4: 3015, 2: 3005, 3: 3001, 1: 2979})
入力シーケンスの長さが非常に大きく得ることができる唯一の2または3のプールであれば典型的な出力が、より長い配列のために、それは一般的にわずか数の値を保持します。
最後に、ここで正確均一な分布を与えるのバージョンがあります。無限ループに陥る可能性があるため、2(またはそれ以下)の要素からなる入力シーケンスでは使用しないでください。とにかく、そのような入力シーケンスのためのソリューションは2つしかありません。 :)
私はこのかなり醜いコードを誇りに思っていませんが、少なくともそれは仕事をします。長さ60の出力リストを作成して画面にうまく収まるようにしていますが、このコードでははるかに大きなシーケンスを生成するのに問題はありません。
from random import shuffle
from itertools import groupby
from collections import Counter
def non_repeating(seq, copies=3):
seq = seq * copies
while True:
shuffle(seq)
result, pool = [], []
for k, g in groupby(seq):
result.append(k)
n = len(list(g)) - 1
if n:
pool.extend(n * [k])
for u in pool:
for i in range(len(result) - 1):
if result[i] != u != result[i + 1]:
result.insert(i+1, u)
break
else:
break
else:
return result
# Test that sequence doesn't contain repeats
def verify(seq):
return all(len(list(g)) == 1 for _, g in groupby(seq))
seq = [1, 2, 3, 4]
result = non_repeating(seq, 15)
print(''.join(map(str, result)))
print(verify(result))
print(Counter(result))
典型的な出力
241413414241343212423232123241234123124342342141313414132313
True
Counter({1: 15, 2: 15, 3: 15, 4: 15})
'しかし、何かがwork' <いません - あなたはここで何を意味するか説明してくださいだろうか?観測される出力は何ですか?あなたはどんな出力をしたいですか?どのように2つの違いはありますか? – inspectorG4dget
数字は連続してはいけません。リストには[1,1]があってはいけません。しかし、これが事実です。 seq_CG [-1]は、実際のリストの最後をとらないと思います。 – SDahm
'数値は連続してはいけません。' '[1,1]'は 'randomList'にあってはならないことを示唆しています。それを超えて、私は本当にあなたがトラブルを抱えていることを理解していません – inspectorG4dget