Hitung probabilitas mendapatkan kepala sebanyak setengah lemparan koin.
Entri polisi (diposting oleh Conor O'Brien): /codegolf//a/100521/8927
Pertanyaan awal: Hitung probabilitas mendapatkan setengah kepala sebanyak lemparan koin.
Solusi diposting memiliki beberapa teknik kebingungan diterapkan, diikuti oleh beberapa lapisan teknik kebingungan yang sama. Setelah melewati beberapa trik pertama, itu menjadi tugas sederhana (jika membosankan!) Untuk mengekstrak fungsi sebenarnya:
nCr(a,b) = a! / ((a-b)! * b!)
result = nCr(x, x/2) / 2^x
Butuh beberapa saat untuk menyadari apa yang saya lihat (untuk sementara saya curiga ada hubungannya dengan entropi), tetapi begitu ranting, saya berhasil menemukan pertanyaan dengan mudah dengan mencari "kemungkinan lemparan koin".
Karena Conor O'Brien menantang penjelasan yang mendalam tentang kode-kodenya, berikut adalah ringkasan dari bit-bit yang lebih menarik:
Itu dimulai dengan mengaburkan beberapa panggilan fungsi bawaan. Ini dicapai dengan basis-32 mengkodekan nama-nama fungsi, kemudian menugaskan mereka ke nama namespace global baru dari satu karakter. Hanya 'atob' yang benar-benar digunakan; 2 lainnya hanya ikan haring merah (eval mengambil steno yang sama dengan atob, hanya untuk diganti, dan btoa tidak digunakan).
_=this;
[
490837, // eval -> U="undefined" -> u(x) = eval(x) (but overwritten below), y = eval
358155, // atob -> U="function (M,..." -> u(x) = atob(x)
390922 // btoa -> U="function (M,..." -> n(x) = btoa(x), U[10] = 'M'
].map(
y=function(M,i){
return _[(U=y+"")[i]] = _[M.toString(2<<2<<2)]
}
);
Berikutnya ada beberapa perpaduan string sepele untuk menyembunyikan kode. Ini mudah dibalik:
u(["","GQ9ZygiYTwyPzE6YSpk","C0tYSki","SkoYSkvZChhLWIpL2QoYikg"].join("K"))
// becomes
'(d=g("a<2?1:a*d(--a)"))(a)/d(a-b)/d(b) '
u("KScpKWIsYShFLCliLGEoQyhEJyhnLGM9RSxiPUQsYT1D").split("").reverse().join("")
// becomes
"C=a,D=b,E=c,g('D(C(a,b),E(a,b))')"
Sebagian besar kebingungan adalah penggunaan g
fungsi, yang hanya mendefinisikan fungsi-fungsi baru. Ini diterapkan secara rekursif, dengan fungsi mengembalikan fungsi baru, atau membutuhkan fungsi sebagai parameter, tetapi akhirnya disederhanakan. Fungsi yang paling menarik untuk keluar dari ini adalah:
function e(a,b){ // a! / ((a-b)! * b!) = nCr
d=function(a){return a<2?1:a*d(--a)} // Factorial
return d(a)/d(a-b)/d(b)
}
Ada juga trik terakhir dengan baris ini:
U[10]+[![]+[]][+[]][++[+[]][+[]]]+[!+[]+[]][+[]][+[]]+17..toString(2<<2<<2)
// U = "function (M,i"..., so U[10] = 'M'. The rest just evaluates to "ath", so this just reads "Math"
Meskipun karena bit berikutnya adalah ".pow (T, a)", itu selalu sangat mungkin bahwa itu harus menjadi "Matematika"!
Langkah-langkah yang saya ambil di sepanjang rute perluasan fungsi adalah:
// Minimal substitutions:
function g(s){return Function("a","b","c","return "+s)};
function e(a,b,c){return (d=g("a<2?1:a*d(--a)"))(a)/d(a-b)/d(b)}
function h(a,b,c){return A=a,B=b,g('A(a,B(a))')}
function j(a,b,c){return a/b}
function L(a,b,c){return Z=a,Y=b,g('Z(a,Y)')}
k=L(j,T=2);
function F(a,b,c){return C=a,D=b,E=c,g('D(C(a,b),E(a,b))')}
RESULT=F(
h(e,k),
j,
function(a,b,c){return _['Math'].pow(T,a)}
);
// First pass
function e(a,b){
d=function(a){return a<2?1:a*d(--a)}
return d(a)/d(a-b)/d(b)
}
function h(a,b){
A=a
B=b
return function(a){
return A(a,B(a))
}
}
function j(a,b){ // ratio function
return a/b
}
function L(a,b){ // binding function (binds param b)
Z=a
Y=b
return function(a){
return Z(a,Y)
}
}
T=2; // Number of states the coin can take
k=L(j,T); // function to calculate number of heads required for fairness
function F(a,b,c){
C=a
D=b
E=c
return function(a,b,c){return D(C(a,b),E(a,b))}
}
RESULT=F(
h(e,k),
j,
function(a){return Math.pow(T,a)}
);
// Second pass
function e(a,b){...}
function k(a){
return a/2
}
function F(a,b,c){
C=a
D=b
E=c
return function(a,b,c){return D(C(a,b),E(a,b))}
}
RESULT=F(
function(a){
return e(a,k(a))
},
function(a,b){
return a/b
},
function(a){return Math.pow(2,a)}
);
// Third pass
function e(a,b) {...}
C=function(a){ // nCr(x,x/2) function
return e(a,a/2)
}
D=function(a,b){ // ratio function
return a/b
}
E=function(a){return Math.pow(2,a)} // 2^x function
RESULT=function(a,b,c){
return D(C(a,b),E(a,b))
}
Struktur fungsi bersarang didasarkan pada utilitas; fungsi "D" / "j" paling luar menghitung rasio, kemudian fungsi "C" / "h" dan "E" (sebaris) paling dalam menghitung jumlah flip koin yang diperlukan. Fungsi "F", dihapus pada lintasan ketiga, bertanggung jawab untuk menghubungkan ini bersama-sama menjadi keseluruhan yang dapat digunakan. Demikian pula fungsi "k" bertanggung jawab untuk memilih jumlah kepala yang perlu diamati; tugas yang didelegasikan ke fungsi rasio "D" / "j" melalui fungsi pengikatan parameter "L"; digunakan di sini untuk memperbaiki parameter b
ke T
(di sini selalu 2, menjadi jumlah negara yang dapat diambil koin).
Pada akhirnya, kita mendapatkan:
function e(a,b){ // a! / ((a-b)! * b!)
d=function(a){return a<2?1:a*d(--a)} // Factorial
return d(a)/d(a-b)/d(b)
}
RESULT=function(a){
return e(a, a/2) / Math.pow(2,a)
}