関数Rand5()が提供されます。この関数は、1から5までの完全にランダムな(等分布)整数を返します。
Rand5()を使用して1から7までの完全にランダムな整数を生成する関数Rand7()を提供します。
関数Rand5()が提供されます。この関数は、1から5までの完全にランダムな(等分布)整数を返します。
Rand5()を使用して1から7までの完全にランダムな整数を生成する関数Rand7()を提供します。
回答:
Java-61文字
int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}
検証用のテストドライバー:
class Rand {
public static void main(String[] args) {
int[] nums = new int[7];
// get a lot of numbers
for(int i = 0; i < 10000000; i++) nums[rand7()-1]++;
// print the results
for(int i = 0; i < 7; i++) System.out.println((i+1) + ": " + nums[i]);
}
// just for rand5()
static java.util.Random r = new java.util.Random();
static int rand5() {
return r.nextInt(5)+1; // Random.nextInt(n) returns 0..n-1, so add 1
}
static int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}
}
結果
C:\Documents and Settings\glowcoder\My Documents>java Rand
1: 1429828
2: 1429347
3: 1428328
4: 1426486
5: 1426784
6: 1429853
7: 1429374
C:\Documents and Settings\glowcoder\My Documents>
rand5
。単純な行列代数を使用してMapleで計算しましたが、必要に応じて数分で鉛筆と紙を使って計算できます。とにかく、Omarはすでに数日前に別の回答へのコメントで同じ数字(正規化要因なし)を投稿していることがわかりました。(また、コメントごとに1人のユーザーにのみ@notifyできますが、投稿の作者には常に通知されます。)
sub rand7{($x=5*&rand5+&rand5-3)<24?int($x/3):&rand7}
さらに、三項演算子と再帰を使用できます。史上最高の日!
OK、divの代わりにmodを使用する場合は47文字:
sub rand7{($x=5*&rand5+&rand5)<27?$x%7+1:&rand7}
&
記号をドロップすると、46文字(現在のバージョンを48にするスペースを含む)になります。
Common Lisp 70文字の場合:
(defun rand7()(let((n(-(+(rand5)(* 5(rand5)))5)))(if(> n 7)(rand7)n)))
括弧は、私が望むよりも多くのスペースを占有します。
(defun rand7()(setq n(-(+(rand5)(* 5(rand5)))5))(if(> n 7)(rand7)n))
(defun rand7()(if(>(setq n(-(+(rand5)(* 5(rand5)))5))7)(rand7)n))
while(x>7)
ですので、有効な範囲内の数値によってのみ満たされます。
ダンマクグラスに投稿された回答からPHPへの翻訳。
function Rand7(){$x=8;while($x>7)$x=rand5()+5*rand5()-5;return $x;}
67文字。
R(統計計算用に構築された言語)では、意図的に不正なソリューション:
# Construct a Rand5 function
Rand5 <- function() sample(seq(5),1)
# And the golf
Rand7=function(r=Rand5())sample(1:(r/r+6),1)
# Or (same character count)
Rand7=function(r=Rand5())sample.int(r/r+6,1)
# Or even shorter(thanks to @Spacedman)
Rand7=function()sample(7)[Rand5()]
引数の遅延評価のおかげで、セミコロンとブレースを削除しました。
10 ^ 6を超える複製の出力:
> test <- replicate(10^6,Rand7())
> table(test)
test
1 2 3 4 5 6 7
142987 142547 143133 142719 142897 142869 142848
library(ggplot2)
qplot(test)
Rand7=function(){r=Rand5();sample(7)[r]}
Rand7=function(){sample(7)[Rand5()]}
def rand7:Int={val r=5*(rand5-1)+rand5
if(r<8)r else rand7}
rand5からの2つの入力:
\ 1 2 3 4 5
1 1 2 3 4 5
2 6 7 8 ..
3 11 ..
4 ..
5
最初の1に5を掛け、2番目を追加します。ほとんどの結果は無視され、新しい計算につながります。結果は、1〜25の値の均等な分布になるはずです。最初の7つの値のみを選択します。モジュロを構築して最初の21を受け入れることもできますが、これによりコードが長くなります。
失敗した歴史的なコードですが、それほど明白ではありません。指摘してくれたIlmari Karonenに感謝します。
def rand7=(1 to 7).map(_=>rand5).sum%7+1
'sum'を非常に簡単にしたこのscala-2.8.0-approachに対して、竹下義輝に感謝します。以前の私の解決策:
def rand7=((0/:(1 to 7))((a,_)=>a+rand5-1))%7+1
rand5:
val rnd = util.Random
def rand5 = rnd.nextInt (5) + 1
def rand7=(1 to 7).map(_=>rand5).sum%7+1
int Rand4()
{
int r = Rand5();
return r > 4 ? Rand4() : r;
}
inline int Rand8()
{
return (Rand4() - 1) << 2 + Rand4();
}
int Rand7()
{
int r = Rand8();
return r > 7 ? Rand7() : r;
}
int Rand4(){int r=Rand5();return r>4?Rand4():r;}int Rand7(){int r=Rand4()-1<<2+Rand4();return r>7?Rand7():r;}
int Rand7()
{
int r = Rand5();
int n = 5;
do {
r = (r - 1) * 5 + Rand5();
int m = n * 5 / 7 * 7;
if (r <= m) {
return r % 7 + 1;
}
r -= m;
n = n * 5 - m;
} while (1);
}
数分布(1000000整数):
142935 142751 142652 143299 142969 142691 142703
生成された整数ごとのRand5()の呼び出しの平均数は約2.2(2〜10+)です。
1 2 3 4 5 6 7 8 9 10
0 840180 112222 44433 2212 886 0 60 6 1
Pythonで間違っている可能性がある別のソリューション:
rand7 = lambda: sum(rand5() for i in range(7)) % 7 + 1
これは単純すぎるようですが、私が試してみると:
counter = [0] * 7
for i in range(100000):
counter[rand7()] += 1
適度に均等な分布が得られます(すべて14000〜14500)。
さて、今、誰かがこの投稿に投票したとき:この解決策は本当に正しいですか?人々にそれを批判させるために、私はこれをここに投稿しました。まあ、それが正しい場合、私のゴルフバージョンは次のようになります。
rand7=lambda:eval("+rand5()"*7)%7+1
37文字になります。
Java、65文字:
int rand7(){int r;do{r=rand5()+5*rand5()-5;}while(r>7);return r;}
def rand7():
while True:
n=5*(rand5()-1)+(rand5()-1)
if n<21:return n%7+1
しかし、ここの推論に基づいて完全に正しい。
sub rand7{1while($_=5*&rand5-rand5)>6;$_+1}
これによりについての警告が表示されますがAmbiguous use of -rand5 resolved as -&rand5()
、正常に機能します。&
また、2番目のrand5
呼び出しの先頭に追加すると、1回のストロークで修正されます。(逆に、プロトタイプで定義されている場合、もう一方&
も削除できます。) rand5
()
追伸 次の46文字バージョンは、約3倍高速です。
sub rand7{1while($_=5*&rand5-rand5)>20;$_%7+1}
int rand7(){int s;while((s=rand5()*5+rand5())<10);return(s%7+1);}
以前のルーチンよりも長いですが、これはより短時間で均一に分布した数値を返すと思います。
PostScript(46)
これはバイナリトークンエンコーディングを使用するため、hexdumpがあります。
00000000 2f 72 61 6e 64 37 7b 38 7b 92 38 37 92 61 7b 92 |/rand7{8{.87.a{.|
00000010 40 7d 69 66 92 75 32 7b 72 61 6e 64 35 7d 92 83 |@}if.u2{rand5}..|
00000020 35 92 6c 92 01 35 92 a9 7d 92 65 7d 92 33 |5.l..5..}.e}.3|
0000002e
これは、テスト用のコードとともに、コメント化されていないコードです。
% This is the actual rand7 procedure.
/rand7{
8{ % potentialResult
% only if the random number is less than or equal to 7, we're done
dup 7 le{ % result
exit % result
}if % potentialResult
pop % -/-
2{rand5}repeat % randomNumber1 randomNumber2
5 mul add 5 sub % randomNumber1 + 5*randomNumber2 - 5 = potentialResult
}loop
}def
%Now, some testing code.
% For testing, we use the built-in rand operator;
% Doesn't really give a 100% even distribution as it returns numbers
% from 0 to 2^31-1, which is of course not divisible by 5.
/rand5 {
rand 5 mod 1 add
}def
% For testing, we initialize a dict that counts the number of times any number
% has been returned. Of course, we start the count at 0 for every number.
<<1 1 7{0}for>>begin
% Now we're calling the function quite a number of times
% and increment the counters accordingly.
1000000 {
rand7 dup load 1 add def
}repeat
% Print the results
currentdict{
2 array astore ==
}forall
int result = 0;
for (int i = 0; i++; i<7)
if (((rand(5) + rand(5)) % 2) //check if odd
result += 1;
return result + 1;
rand7を定義します。
rand7=function(n)sample(7,n,T)
Rは統計分析を念頭に置いて作成されたため、このタスクは簡単であり、組み込み関数を使用して、sample
置換をTRUEに設定しています。
サンプル出力:
> rand7(20)
[1] 4 3 6 1 2 4 3 2 3 2 5 1 4 6 4 2 4 6 6 1
> rand7(20)
[1] 1 2 5 2 6 4 6 1 7 1 1 3 7 6 4 7 4 2 1 2
> rand7(20)
[1] 6 7 1 3 3 1 5 4 3 4 2 1 5 4 4 4 7 7 1 5
Rand7=Rand5[]~Sum~{7}~Mod~7+1&
int m=0;int rand7(){return(m=m*5&-1>>>1|rand5())%7+1;}
配布テスト:
[1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]
アルゴリズム:
>数値は相互に無相関ではなくなり、個別に完全にランダムになりました。
C / C ++コードのコアコードには1行しかありません!
static unsigned int gi = 0;
int rand7()
{
return (((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1;
}
//call this seed before rand7
//maybe it's not best seed, if yo have any good idea tell me please
//and thanks JiminP again, he remind me to do this
void srand7()
{
int i, n = time(0);
for (i = 0; i < n % 7; i++)
rand7();
}
srand7()はrand7のシードです。Cでrandの前にsrandを呼び出すように、rand7の前にこの関数を呼び出す必要があります。
これは非常に良い方法です。rand()を1回だけ呼び出し、ループ処理も余分なメモリも消費しないためです。
説明しましょう:サイズが5の整数配列を考えてみましょう:
1st get one number from 1 2 3 4 5 by rand5
2nd get one number from 2 3 4 5 6
3rd get one number from 3 4 5 6 7
4th get one number from 4 5 6 7 1
5th get one number from 5 6 7 1 2
5th get one number from 6 7 1 2 3
7th get one number from 7 1 2 3 4
TABLEを取得し、1〜7のそれぞれが5回出現し、35個すべての数字があるため、各数字の確率は5/35 = 1/7です。そして次回は
8th get one number from 1 2 3 4 5
9th get one number from 2 3 4 5 6
......
十分な時間の後、1-7の均一な分布を得ることができます。
したがって、ループ左シフトによって1〜7の5つの要素を復元する配列を割り当て、rand5によって毎回配列から1つの数値を取得できます。代わりに、前に7つの配列すべてを生成し、それらを循環的に使用できます。コードもシンプルで、多くの短いコードでこれを行うことができます。
ただし、%演算のプロパティを使用できるため、表1-7の行は(rand5 + i)%7と同等です。つまり、C言語ではa = rand()%5 + 1はrand5、b = gi ++です。 %7は上の表のすべての順列を生成し、0-6は1-7を置き換えますc =(a + b)%7 + 1は、1-7を均一に生成します。最後に、このコードを得ました:
(((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1
ただし、最初の呼び出しで6と7を取得できないため、最初の正式な呼び出しの順列を乱すために、C / C ++のrand for randのようなシードが必要です。
テストの完全なコードは次のとおりです。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static unsigned int gi = 0;
//a = rand() % 5 + 1 is rand5 in C language,
//b = gi++ % 7 generates all permutations,
//c = (a + b) % 7 + 1, generates 1 - 7 uniformly.
//Dont forget call srand7 before rand7
int rand7()
{
return (((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1;
}
//call this seed before rand7
//maybe it's not best seed, if yo have any good idea tell me please
//and thanks JiminP again, he remind me to do this
void srand7()
{
int i, n = time(0);
for (i = 0; i < n % 7; i++)
rand7();
}
void main(void)
{
unsigned int result[10] = {0};
int k;
srand((unsigned int)time(0)); //initialize the seed for rand
srand7() //initialize the rand7
for (k = 0; k < 100000; k++)
result[rand7() - 1]++;
for (k = 0; k < 7; k++)
printf("%d : %.05f\n", k + 1, (float)result[k]/100000);
}
6
か7
、一度呼び出すことで取得できますか?
int main(){if(rand7()==6) printf("Hello, world!");}
、ループを使用した近似は 'Hello、world!'を出力します。7回に1回ですが、コードはそうではありません。