壊れたランダム関数を修正


18

友人のコンピューターにアドオンカードがあり、1から5までの完全に乱数を生成します。残念ながら、彼らは何とかコーラをこぼし、1から4までのすべての数値に対して2だけを生成します。幸いなことに、ランダム性は保持されますが、2は80%の確率で、5は20%の確率で、 1、3、または4が生成されます。このランダムなソース(それを呼び出すBrokenRand()か、類似のもの)を使用して、元のソースと同じ完全なランダム性で等しい20%の確率でそれぞれ1から5までの数を生成する動作乱数ジェネレーターを記述します。

最短のプログラムが勝ちます。BrokenRand人口統計学的に選択されたカスタマーサービスフォーカスコンサルタントによる公平な最低通話数に対して、年齢と性別に分類されたボーナスポイント-私。

回答:


10

JavaScript-69文字

これは、フォンノイマン抽出器を使用して不偏ビットを生成します。一般的なアルゴリズムは、HotBitsのWebサイトにも記載されています。3ビットを使用して0から7までの数字が形成されます。5以上の数字はすべて破棄され、残りの各数字に1が加算されてから印刷されます。これに大きな偏りがないことを示すためにシミュレーションを行いました。

r()RNGにアクセスするには、独自の関数を提供する必要があります。

 for(;;v<5&&alert(v+1))for(v=i=0;i<3;a-b&&(v*=2,v+=a<b,i++))b=r(a=r())

これは本当によくできています!増分値を短絡する方法が好きです。
-snmcdonald

7ビットを生成し、3つの乱数を抽出してBrokenRandの呼び出しを減らすことができますが、それはおそらくさらにストロークがかかるでしょう
-gnibbler

5

scala 79文字:

// preparation: 
val r = util.Random 
def defektRNG = if (r.nextInt (5) == 0) 5 else 2 

(1 to 20).foreach (_ => print (" " + defektRNG))
// first impression:
// 2 2 2 2 2 2 2 5 2 2 5 2 2 2 5 2 2 2 2 2

def rnd : Int = { val k = (1 to 5).map (_ => defektRNG)
  if (k.sum == 13) k.findIndexOf (_ == 5) + 1 else rnd } 

// first impression:
(1 to 20).foreach (_ => print (" " + rnd))             
// 3 3 2 3 5 2 2 5 1 1 3 4 3 2 5 3 3 1 5 4
// control:
(1 to 50000).map (_ => rnd).groupBy (identity) .map (_._2.length) 
// scala.collection.immutable.Iterable[Int] = List(10151, 9997, 9971, 9955, 9926)

本物のゴルフでは、defektRNGエイリアスbrokenRandの名前がbに変更されました。

def r:Int={val k=(1 to 5).map(_=>b)
if(k.sum==13)k.findIndexOf(_==5)+1 else r} 

仕組み:ほとんどの場合、bは2のシーケンスを返します。しかし、bを5回呼び出した場合、結果は4x2と1x5で終わることが非常に多く、これは2番目に確率の高いイベントであり、5-2-2-2-2、2-5-2-2 -2、2-2-5-2-2、2-2-2-5-2、2-2-2-2-5。

これらは共通しており、合計は4 * 2 + 5 = 13です。最初の5つのインデックスを使用して、有効な乱数を定義できます。1つより多いまたは少ない5、合計が13より多い、または少ない場合、繰り返します。

「rnd」(別名「r」)のカウンターは、番号を生成するのに平均で何回の呼び出しが必要かを示すことができます。50 000の乱数に対してrへの121 200の呼び出しがありますが、これは印象的ではありません。:)


3

> <>(魚) -55バイト

scalaの回答で不明な@userと同じアルゴリズムを使用するように更新

<v?= d +&:i&+&:i&+&:i&+&:i&:i
 0
 > 1 + $ 5(?vnao;
 ^ <

壊れたジェネレーターがstdinに接続されることを想定しています。これが私が使用しpythonスクリプトです。コードは現在のFish仕様と一致していますが、古いインタープリターの修正バージョンを使用しました。

bash:$ for i in $(seq 1000); do ./bad_rand.py | ./myfish.py rand.fish; done >res.txt
bash:$ for i in $(seq 5); do echo -n "$i : "; grep -c $i res.txt; done
1 : 193
2 : 204
3 : 198
4 : 206
5 : 199

より大きなサンプルを実行しますが、時間がかかります。


2

GolfScript、23バイト

遅い答えですが、これはたまたまフロントページに現れたので...

0{;[{r}5*].5?)\5-,4-}do

ユーザーunknownのScalaソリューションと同じアルゴリズムを使用します。バイアス付き乱数ジェネレーターは、という名前のGolfScriptサブルーチンとして提供されると仮定しrます。次のように、適切なバイアスRNGを自分で定義できます。

{5rand!3*2+}:r;

バイアスがないことを示す簡単なテストを次に示します。 残念ながら、オンラインGolfScriptサーバーは少し遅いので、時間通りに完了するためにデモを100サンプルに削減する必要がありました。GolfScriptインタープリターを使用してテストをローカルで実行する場合は、100*to 1000*またはを増やしてみてください10000*

(GolfScriptサーバーは時々ランダムにフリーズしてタイムアウトすることもあります。これが発生した場合は、通常再試行しても解決します。他のコードでも発生し、自分のコンピューターではなくサーバーでのみ発生します。私のコードではなく、サーバーに問題があること。)


-1

javascript、読みやすさまたは 最適化を低下させない160文字

function giveRandom(){
    var result = Math.floor(5 * Math.random()) + 1;
    while(BrockenRand() != 5){
        result = Math.floor(5 * Math.random()) + 1;
    }
    return result;
}

@ snmcdonald-その一部はタイプミスではなく、完全にランダムなジェネレーター(完全にランダム!)のみを承認することでjs randomを改善する方法です20%結果
-www0z0k

BrockenBand()それでは何を説明するのですか?
Mateen Ulhaq

6
ポイントを逃したと思う
-cthom06

@muntoo-意味BrockenRand
-www0z0k

この方法で数バイトを保存しますfunction giveRandom(){return Math.ceil(Math.random()*5)}
。– user300375
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.