Anda diberi fungsi Rand5 (). Fungsi ini mengembalikan bilangan bulat acak (distribusi yang sama) antara 1 dan 5.
Berikan fungsi Rand7 (), yang menggunakan Rand5 () untuk menghasilkan bilangan bulat acak sempurna antara 1 dan 7.
Anda diberi fungsi Rand5 (). Fungsi ini mengembalikan bilangan bulat acak (distribusi yang sama) antara 1 dan 5.
Berikan fungsi Rand7 (), yang menggunakan Rand5 () untuk menghasilkan bilangan bulat acak sempurna antara 1 dan 7.
Jawaban:
Jawa - 61 karakter
int rand7(){int s=0,c=7;while(c-->0)s+=rand5();return s%7+1;}
Driver penguji untuk validasi:
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;}
}
Hasil
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
. Saya menghitungnya di Maple menggunakan aljabar matriks sederhana, tetapi Anda bisa melakukannya dengan pensil dan kertas dalam beberapa menit jika Anda mau. Lagi pula, ternyata Omar sudah memposting angka yang sama (tanpa faktor normalisasi) dalam komentar untuk jawaban lain beberapa hari sebelumnya. (Juga ps., Anda hanya dapat @memberitahu satu pengguna per komentar, meskipun penulis posting selalu diberitahu.)
sub rand7{($x=5*&rand5+&rand5-3)<24?int($x/3):&rand7}
Plus saya bisa menggunakan operator ternary DAN rekursi. Hari terbaik yang pernah ada!
OK, 47 karakter jika Anda menggunakan mod, bukan div:
sub rand7{($x=5*&rand5+&rand5)<27?$x%7+1:&rand7}
&
tanda terakhir untuk membuatnya menjadi 46 karakter (termasuk ruang, yang menempatkan versi Anda saat ini di 48).
Ruby - 54 karakter (berdasarkan solusi Dan McGrath, menggunakan loop)
def rand7;x=8;while x>7 do x=rand5+5*rand5-5 end;x;end
Ruby - 45 karakter (solusi yang sama, menggunakan rekursi)
def rand7;x=rand5+5*rand5-5;x>7 ?rand7: x;end
(x=rand5+5*rand5-5)>7?
.
Dalam Common Lisp 70 karakter:
(defun rand7()(let((n(-(+(rand5)(* 5(rand5)))5)))(if(> n 7)(rand7)n)))
Tanda kurung mengambil lebih banyak ruang daripada yang saya inginkan.
(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))
Dalam c / c ++ menggunakan rejection sampling
int rand7(){int x=8;while(x>7)x=rand5()+5*rand5()-5;return x;}
62 karakter.
while(x>7)
, jadi itu hanya akan dipenuhi oleh angka dalam rentang yang valid.
Terjemahan ke PHP, dari jawaban yang diposting ny Dan McGrath.
function Rand7(){$x=8;while($x>7)$x=rand5()+5*rand5()-5;return $x;}
67 karakter.
Dalam R (bahasa yang dibangun untuk perhitungan statistik), solusi yang sengaja dibuat curang:
# 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()]
Berkat evaluasi argumen yang malas, saya menghilangkan titik koma dan kawat gigi.
Output lebih dari 10 ^ 6 replikasi:
> 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}
dengan 2 input dari rand5:
\ 1 2 3 4 5
1 1 2 3 4 5
2 6 7 8 ..
3 11 ..
4 ..
5
Saya kalikan yang pertama-1 dengan 5, dan tambahkan yang kedua. Sebagian besar hasil diabaikan, dan mengarah ke perhitungan baru. Hasilnya harus berupa distribusi nilai yang sama dari 1-25, dari mana saya hanya memilih 7 yang pertama. Saya bisa menerima 21 pertama dengan membangun modulo, tetapi ini akan menyebabkan kode lebih lama.
kode bersejarah yang gagal, tetapi tidak terlalu jelas. Terima kasih kepada Ilmari Karonen karena menunjukkannya:
def rand7=(1 to 7).map(_=>rand5).sum%7+1
Terima kasih kepada Yoshiteru Takeshita, untuk pendekatan scala-2.8.0 yang menjadikan 'jumlah' ini begitu mudah. Solusi saya sebelumnya:
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;}
Terjemahan ke Javascript, dari jawaban yang diposting oleh Dan McGrath.
function Rand7(){x=8;while(x>7)x=rand5()+5*rand5()-5;return x}
62 karakter
function Rand7(){for(x=8;x>7;x=rand5()+5*rand5()-5);return x}
sedikit lebih pendek: P
function Rand7(){for(x=0,i=1;i<8;x^=i*((k=Rand5())%2),i*=1+(k<5));return x?x:Rand7()}
Saya tahu ada jawaban yang lebih pendek, tetapi saya ingin menunjukkan tes teka-teki ini. Ternyata hanya jawaban Clyde Lobo yang menggunakan sampel penolakan Dan McGrath yang benar (di antara jawaban JS).
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);
}
Distribusi angka (1000000 bilangan bulat):
142935 142751 142652 143299 142969 142691 142703
Jumlah rata-rata panggilan ke Rand5 () per setiap bilangan bulat yang dihasilkan adalah sekitar 2,2 (2 hingga 10+).
1 2 3 4 5 6 7 8 9 10
0 840180 112222 44433 2212 886 0 60 6 1
Di Jawa (atau C / C ++ saya kira)
menggunakan formula generasi oleh Alexandru, dalam 65 karakter:
int rand7(){int x=rand5()*5+rand5()-6;return x>20?rand7():x/3+1;}
menggunakan formula generasi oleh Dan McGrath, dalam 60 karakter
int rand7(){int x=rand5()+5*rand5()-5;return x>7?rand7():x;}
Solusi lain yang mungkin salah, dengan Python:
rand7 = lambda: sum(rand5() for i in range(7)) % 7 + 1
Ini tampaknya terlalu sederhana, tetapi ketika saya mencoba:
counter = [0] * 7
for i in range(100000):
counter[rand7()] += 1
Saya mendapatkan distribusi yang cukup merata (semuanya antara 14000 dan 14500).
Oke, sekarang ketika seseorang memberikan suara untuk posting ini: Apakah solusi ini memang benar? Saya lebih banyak memposting ini di sini untuk membuat orang mengkritiknya. Nah, jika itu benar, versi golf saya adalah:
rand7=lambda:eval("+rand5()"*7)%7+1
yang keluar untuk 37 karakter.
Jawa, 65 karakter:
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
tetapi sepenuhnya benar berdasarkan alasan di sini .
sub rand7{1while($_=5*&rand5-rand5)>6;$_+1}
Ini memberi peringatan tentang Ambiguous use of -rand5 resolved as -&rand5()
, tetapi berfungsi dengan benar. Membutuhkan &
juga rand5
panggilan kedua untuk memperbaikinya dengan biaya satu pukulan. (Sebaliknya, yang lain &
juga bisa dihapus jika rand5
sudah didefinisikan dengan a()
prototipe.)
Ps. Versi 46-char berikut sekitar tiga kali lebih cepat:
sub rand7{1while($_=5*&rand5-rand5)>20;$_%7+1}
int rand7(){int s;while((s=rand5()*5+rand5())<10);return(s%7+1);}
Lebih lama dari rutinitas sebelumnya, tapi saya pikir yang ini mengembalikan angka yang terdistribusi secara seragam dalam waktu yang lebih singkat.
PostScript (46)
Ini menggunakan pengkodean token biner, oleh karena itu, inilah 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
Untuk mencobanya, Anda juga dapat mengunduhnya .
Berikut adalah kode yang tidak ditandai dan dikomentari, bersama dengan kode pengujian.
% 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;
Tentukan rand7:
rand7=function(n)sample(7,n,T)
Karena R ditulis dengan analisis statistik dalam pikiran, tugas ini sepele, dan saya menggunakan fungsi bawaan sample
bawaan dengan penggantian diatur ke TRUE.
Output sampel:
> 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&
Bagaimana dengan ini?
int Rand7()
{
return Rand5()+ Rand5()/2;
}
/
operatornya melakukan bilangan bulat matematika? Apa yang terjadi pada hasil Anda jika itu desimal, floating-point, atau bilangan bulat matematika?
[2/25, 4/25, 5/25, 5/25, 5/25, 3/25, 1/25]
. Tidak persis seragam.
int m=0;int rand7(){return(m=m*5&-1>>>1|rand5())%7+1;}
Tes distribusi:
[1000915, 999689, 999169, 998227, 1001653, 1000419, 999928]
Algoritma:
> Angka-angka tidak saling tidak berhubungan lagi, tetapi secara individual sangat acak.
Kode C / C ++ kode inti hanya memiliki satu baris!
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();
}
The srand7 () adalah benih rand7, harus memanggil fungsi ini sebelum rand7, sama seperti panggilan srand sebelum rand di C.
Ini sangat bagus, karena memanggil rand () hanya satu kali, dan tidak ada perulangan, tidak ada memori tambahan yang dikeluarkan.
Mari saya jelaskan: pertimbangkan array integer dengan ukuran 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
Jadi kami mendapatkan TABEL, masing-masing 1-7 muncul 5 kali di dalamnya, dan memiliki semua 35 angka, sehingga probabilitas setiap angka adalah 5/35 = 1/7. Dan lain kali,
8th get one number from 1 2 3 4 5
9th get one number from 2 3 4 5 6
......
Setelah cukup waktu, kita bisa mendapatkan distribusi seragam 1-7.
Jadi, kita bisa mengalokasikan array untuk mengembalikan lima elemen 1-7 dengan loop-kiri-shift, dan mendapatkan satu angka dari array setiap kali dengan rand5. Sebagai gantinya, kita dapat menghasilkan ketujuh array sebelumnya, dan menggunakannya secara melingkar. Kodenya juga sederhana, sudah banyak kode pendek yang bisa melakukan ini.
Tapi, kita bisa menggunakan properti% operasi, sehingga tabel 1-7 baris setara dengan (rand5 + i)% 7, yaitu: a = rand ()% 5 + 1 adalah rand5 dalam bahasa C, b = gi ++ % 7 menghasilkan semua permutasi pada tabel di atas, dan 0 - 6 ganti 1 - 7 c = (a + b)% 7 + 1, menghasilkan 1 - 7 secara seragam. Akhirnya, kami mendapat kode ini:
(((rand() % 5 + 1) + (gi++ % 7)) % 7) + 1
Tapi, kita tidak bisa mendapatkan 6 dan 7 pada panggilan pertama, jadi kita perlu sebuah seed, beberapa seperti srand untuk rand di C / C ++, untuk mengatur permutasi untuk panggilan formal pertama.
Berikut ini kode lengkap untuk pengujian:
#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
atau 7
meneleponnya sekali ?
int main(){if(rand7()==6) printf("Hello, world!");}
, perkiraan menggunakan loop akan mencetak 'Halo, dunia!' 1 dalam 7 kali, tetapi kode Anda tidak.