ドア賞を受賞する可能性はありますか?


12

私の地元のACMの章では、会議に参加する人々にドア賞を贈ります。ただし、プログラミングパズルを解くと勝つ可能性が高くなります(ただし、私は常にそのパズルを解きます)。したがって、一部の人には1つのエントリがあり、他の人には2つのエントリがあります。ラッフルプログラムの仕組みは、誰かがパズルを解くときに別のエントリを追加することではありません。代わりに、人が持っている「ライブ」の数を追跡し、その人がランダムサンプリングアルゴリズムの各パスで選択された場合、その人の数を減らします。したがって、次のように機能します。

Doorknob: 1.  xnor: 2.  Justin: 2.  Alex: 1.  Dennis: 2.

次に、プログラムはのいずれかをランダムに選択し[Doorknob, xnor, Justin, Alex, Dennis]、数値をデクリメントします(たとえば、選択しますJustin)。

Doorknob: 1.  xnor: 2.  Justin: 1.  Alex: 1. Dennis: 2.

そして繰り返します。誰かの「ライブ」の数が0Justin再度選択しよう)になった場合、リストから削除されます。

Doorknob: 1.  xnor: 2.  Alex: 1.  Dennis: 2.

これは、一人が残るまで続きます。その人が勝者です。

さて、本当の問題は、私が勝つ可能性はどのくらいだったのかということです。


次の2つの入力が与えられます。

  • n。これはチャレンジに参加した人の数です
  • k。これは、n2人の命を持っている(そのうちの)人の数です。この番号には常にあなたが含まれます。

だから、もし私が関数を持っていてpを呼び出したp(10, 5)場合、それは合計10人の人が賞金を獲得する確率になります。


勝つ確率を正確に、または小数として出力することが期待されています。いずれにしても、答えは4を含め、正確にアップしてある必要があります番目の小数点後の小数点以下の場所。その桁に丸めるかどうかはあなた次第です。

あなたのソリューションは、高い確率で小数 4 までの回答を出力するランダム化ソリューションかもしれません。使用するビルトインRNGは本当にランダムであり、少なくとも90%の確率で正しい答えを出力する必要があると仮定できます。

さらに、コードはのためにのみ動作する必要がありますがn, k <= 1000、好奇心の強い人向けのテストケースよりも大きなテストケースを提供しました。


テストケース

注:これらのいくつかは一般式です。

n,    k   |  output
----------+---------
1,    1   |  1
2,    2   |  0.5
2,    1   |  0.75
3,    1   |  11/18 = 0.611111111
1000, 1   |  0.007485470860550352
4,    3   |  0.3052662037037037
k,    k   |  1/k
n,    1   |  (EulerGamma + PolyGamma[1 + n])/n    (* Mathematica code *)
          |  (γ + ψ(1 + n))/n
10,   6   |  0.14424629234373537
300,  100 |  0.007871966408910648
500,  200 |  0.004218184180294532
1000, 500 |  0.0018008560286627948
---------------------------------- Extra (not needed to be a valid answer)
5000, 601 |  0.0009518052922680399
5000, 901 |  0.0007632938197806958

別のいくつかのチェックについてはp(n, 1) * n、次のようにします。

n     |  output
------+---------
1     | 1
2     | 1.5 
3     | 1.8333333333333335
10    | 2.928968253968254
100   | 5.1873775176396215
-------------------------- Extra (not needed to be a valid answer)
100000| 12.090146129863305

このサイトのタグにはもう慣れていません。より適切なタグを考えている場合は、編集してください!
ジャスティン

math.seに密接に関連する質問:math.stackexchange.com/q/1669715/72616
Justin

したがって、P(n、k)=((k-1)/ n)P(n、k-1)+((nk)/ n)P(n-1、k)+(1 / n)Q( n、k-1)、ここでQ(n、k)=((nk-1)/ n)Q(n-1、k)+(k / n)Q(n、k-1)およびQ(1 、0)= 1 ...
リーキーヌン

@KennyLau私はそれを解釈しようとはしませんが、関数のわずかに異なる定義を使用するため、math.seリンクに注意してください(k1つずれていると思います)
ジャスティン

2
もちろん確実ではありませんが、答えが小数第4位まで正しい確率で十分な試行回数でランダム化されたシミュレーションを行うことは問題ありませんか?
-xnor

回答:


2

MATL、42バイト

:<~QXJx`J`tf1Zry0*1b(-tzq]f1=vts3e8<]6L)Ym

これは、確率論的(モンテカルロ)アプローチを使用します。実験は何度も実行され、そこから確率が推定されます。実現の数は、少なくとも90%の確率で結果が4番目の小数まで正しいことを保証するために選択されます。ただし、これには非常に長い時間と大量のメモリが必要です。以下のリンクでは、実現回数が10 6分の1に削減されているため、プログラムは妥当な時間内に終了します。また、最初の 10進数のみが少なくとも90%の確率で正確であることが保証されます。

編集(2016年7月29日):言語の変更により、6Lに置き換える必要があります3L。以下のリンクには、その変更が組み込まれています。

オンラインでお試しください!

バックグラウンド

してみましょうpが計算される確率を表します。チャレンジで説明されている実験は、n回実行されます。毎回、賞品を獲得する(「成功」)か、獲得しないかのいずれかです。してみましょうNは、成功数とします。望ましい確率は、Nnから推定できます。nが大きいほど、推定はより正確になります。重要な問題は、nを選択して望ましい精度を実現する方法、つまり、エラーの少なくとも90%が10 -4未満になることを保証する方法です。

モンテカルロ法は

  • 固定サイズnの値は事前に固定されています(そしてNはランダムです)。
  • 可変サイズnは、シミュレーション結果によってオンザフライで決定されます。

2番目のカテゴリの中で、一般的に使用される方法は、N(必要な成功数)を修正し、その成功数が達成されるまでシミュレーション続けることです。したがって、nはランダムです。この手法は、逆二項サンプリングまたは負の二項モンテカルロ法と呼ばれ、推定器の精度を制限できるという利点があります。このため、ここで使用されます。

具体的には、負の二項モンテカルロx =(N -1)/(n -1)の場合、pの不偏推定量です。また、xが特定の比率を超えてpから逸脱する確率は上限があります。このペーパーの式(1)に従って(条件(2)も満たされることに注意してください)、N = 2.75・10 8以上を取ると、p / xが少なくとも[90%]の間隔[1.0001、0.9999]に属します。確率。特に、これは、xが必要に応じて少なくとも90%の確率で小数点第4位まで正しいことを意味します。

コードの説明

コードはN = 3e8を使用して1バイトを保存します。これだけ多くのシミュレーションを実行すると、時間がかかることに注意してください。リンク内のコードはN =を使用します300。これは、より妥当な時間(最初のテストケースのオンラインコンパイラで1分未満)で実行されます。ただし、これにより、最初の小数部が少なくとも90%の確率で正しいことが保証されます。

:        % Take k implicitly. Range [1 ... k]
<~       % Take n implicitly. Determine if each element in the previous array is
         % less than or equal than n
Q        % Add 1. This gives an array [2 ... 2 1 ... 1]
XJx      % Copy to clipboard J. Delete from stack
`        % Do...while. Each iteration is a Monte Carlo realization, until the 
         % desired nunber of successes is reached
  J      %   Push previously computed array [2 ... 2 1 ... 1]
  `      %   Do...while. Each iteration picks one door and decrements it, until
         %   there is only one
    t    %     Duplicate
    f    %     Indices of non-zero elements of array
    1Zr  %     Choose one of them randomly with uniform distribution
    y0*  %     Copy of array with all values set to 0
    1b(  %     Assign 1 to chosen index
    -    %     Subtract
    tzq  %     Duplicate. Number of nonzero elements minus 1. This is falsy if
         %     there was only one nonzero value; in this case the loop is exited
  ]      %   End do...while
  f1=    %   Index of chosen door. True if it was 1 (success), 0 otherwise
  v      %   Concatenate vertically to results from previous realizations
  ts3e8< %   Duplicate. Is the sum less than 3e8? If so, the loop is exited
]        % End do...while
6L)      % Remove last value (which is always 1)
Ym       % Compute mean. This gives (N-1)/(n-1). Implicitly display

ハハ私は90%がそれを難し​​くすることに気づかなかった:
ジャスティン

はい、90%の信頼度を持つ4番目の小数部は非常に強力な要件です:
ルイスメンドー

2

Pyth、34バイト

Mc|!*HJ-GHch*J+*tHgGtH*gtGHKh-GHKG

テストスイート

引数としてnkgをとる、決定論的なメモ化された再帰関数を定義します。 約18秒で戻ります(オンラインインタプリタがタイムアウトするため、上記のテストスイートには含まれていません)。g 1000 5000.0018008560286627952

おおよそのPython 3変換は

@memoized
def g(n,k):
    return (not k*(n-k) or (1+(n-k)*((k-1)*g(n,k-1)+g(n-1,k)*(n-k+1)))/(n-k+1))/n

1

JavaScript(ES6)、65バイト

f=(n,k,d=n-k)=>(!d||(f(n-1,k)*++d*--d+1+(--k&&f(n,k)*k*d))/++d)/n

ただし、大きな数字で試してはいけません。f(30、10)でも、かなりの時間がかかります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.