CJam、16 14 13バイト
0{Kmr(+esmr}g
これは、現在のタイムスタンプ(10 12のオーダー)を使用してループを終了する必要があるかどうかを判断するため、非常に長時間実行されます。これは最も短いので、これを提出として使用していますが、2つの14バイトの選択肢があり、それぞれにメリットがあります。
0{esmr(+esmr}g
この1はされないの範囲以来、PRNGの期間によって制限され、すべての乱数は現在のタイムスタンプに依存します。したがって、これは任意の数を生成できるはずです。ただし、負の数、または小さな正の数の確率はゼロになります。
以下は3e5
、タイムスタンプの代わりに使用する同等のバージョンです。そして20
、最初の範囲(13バイトの提出として)。それははるかに高速であり、すべてのルールにも準拠しています。妥当な実行時間と小さなコードサイズを維持しながら、1,000,000を超える数値に対して50%の確率を得るのは、一種の制限的なケースです。説明と数学的正当化は、このバージョンを参照しています。
0{Kmr(+3e5mr}g
通常、これには数秒かかります。をに置き換える5
と、2
さらに高速に実行できます。ただし、50%の確率に関する要件は、1,000,000ではなく1,000でのみ満たされます。
私は0から始めています。それからループがあり、確率1 /(3 * 10 5)で抜け出します。そのループ内で、実行中の合計に-1〜18(両端を含む)のランダムな整数を追加します。正の整数は負の整数よりも可能性が高いため、各整数が出力される確率は(小さいながらも)有限です(生涯に負の整数が表示されるとは思わない)。このような小さな確率でブレークアウトし、ほとんどの時間をインクリメント(および減算よりも多く加算)することで、通常1,000,000を超えることが保証されます。
0 "Push a 0.";
{ }g "Do while...";
Kmr "Get a random integer in 0..19.";
( "Decrement to give -1..18.";
+ "Add.";
3e5mr "Get a random integer in 0..299,999. Aborts if this is 0.";
数学的正当化:
- 各ステップで、平均で8.5を追加します。
- 1,000,000に到達するには、これらのステップのうち117,647が必要です。
このステップ数よりも少ない確率で、
sum(n=0..117,646) (299,999/300,000)^n * 1/300,000
これはに評価され0.324402
ます。したがって、ケースの約3分の2で、117,647のステップが増え、1,000,000ごとに簡単になります。
- (これは正確な確率ではないことに注意してください、それらの平均8.5に多少の変動があるためですが、50%に到達するには、117,646を超えて約210,000ステップに進む必要があります。)
- 疑わしい場合は、終了確率の分母を簡単に爆破できます。
9e9
バイトを追加せずに(ただし、実行時間は何年も)ます。
...または11バイト?
最後に、11バイトのバージョンがあります。これもPRNGの期間によって制限されませんが、ほとんど毎回メモリ不足になります。反復ごとに(タイムスタンプに基づいて)乱数を1つだけ生成し、インクリメントと終了の両方に使用します。各反復の結果はスタックに残り、最後にのみ集計されます。このアイデアをありがとうデニス:
{esmr(}h]:+