pengantar
Dalam tantangan ini, tugas Anda adalah mengimplementasikan kumpulan fungsi sederhana yang bersama-sama membentuk perpustakaan mini yang dapat digunakan untuk distribusi probabilitas sederhana. Untuk mengakomodasi beberapa bahasa yang lebih esoteris yang orang suka gunakan di sini, implementasi berikut dapat diterima:
- Cuplikan kode yang mendefinisikan kumpulan fungsi bernama (atau setara terdekat).
- Kumpulan ekspresi yang mengevaluasi fungsi bernama atau anonim (atau setara terdekat).
- Ekspresi tunggal yang mengevaluasi beberapa fungsi yang disebut atau anonim (atau setara terdekat).
- Kumpulan program independen yang mengambil input dari baris perintah, STDIN atau setara terdekat, dan output ke STDOUT atau setara terdekat.
Fungsinya
Anda harus menerapkan fungsi-fungsi berikut, menggunakan nama yang lebih pendek jika diinginkan.
uniform
mengambil input dua nomor floating pointa
danb
, dan mengembalikan distribusi seragam aktif[a,b]
. Anda dapat mengasumsikan itua < b
; casea ≥ b
tidak terdefinisi.blend
mengambil input tiga distribusi probabilitasP
,Q
danR
. Ini mengembalikan distribusi probabilitasS
, yang menarik nilaix
,y
danz
dariP
,Q
danR
, masing-masing, dan menghasilkany
jikax ≥ 0
, danz
jikax < 0
.over
mengambil sebagai input angka floating pointf
dan distribusi probabilitasP
, dan mengembalikan probabilitas yangx ≥ f
berlaku untuk nomor acak yangx
diambilP
.
Untuk referensi, over
dapat didefinisikan sebagai berikut (dalam pseudocode):
over(f, uniform(a, b)):
if f <= a: return 1.0
else if f >= b: return 0.0
else: return (b - f)/(b - a)
over(f, blend(P, Q, R)):
p = over(0.0, P)
return p*over(f, Q) + (1-p)*over(f, R)
Anda dapat mengasumsikan bahwa semua distribusi probabilitas yang diberikan over
dibangun menggunakan uniform
dan blend
, dan bahwa satu-satunya hal yang akan dilakukan pengguna dengan distribusi probabilitas adalah memberi makan kepada blend
atau over
. Anda dapat menggunakan tipe data yang mudah untuk mewakili distribusi: daftar angka, string, objek khusus, dll. Satu-satunya hal yang penting adalah API bekerja dengan benar. Juga, implementasi Anda harus deterministik, dalam arti selalu mengembalikan output yang sama untuk input yang sama.
Uji kasus
Nilai output Anda harus benar setidaknya dua digit setelah titik desimal pada kasus uji ini.
over(4.356, uniform(-4.873, 2.441)) -> 0.0
over(2.226, uniform(-1.922, 2.664)) -> 0.09550806803314438
over(-4.353, uniform(-7.929, -0.823)) -> 0.49676329862088375
over(-2.491, uniform(-0.340, 6.453)) -> 1.0
over(0.738, blend(uniform(-5.233, 3.384), uniform(2.767, 8.329), uniform(-2.769, 6.497))) -> 0.7701533851999125
over(-3.577, blend(uniform(-3.159, 0.070), blend(blend(uniform(-4.996, 4.851), uniform(-7.516, 1.455), uniform(-0.931, 7.292)), blend(uniform(-5.437, -0.738), uniform(-8.272, -2.316), uniform(-3.225, 1.201)), uniform(3.097, 6.792)), uniform(-8.215, 0.817))) -> 0.4976245638164541
over(3.243, blend(blend(uniform(-4.909, 2.003), uniform(-4.158, 4.622), blend(uniform(0.572, 5.874), uniform(-0.573, 4.716), blend(uniform(-5.279, 3.702), uniform(-6.564, 1.373), uniform(-6.585, 2.802)))), uniform(-3.148, 2.015), blend(uniform(-6.235, -5.629), uniform(-4.647, -1.056), uniform(-0.384, 2.050)))) -> 0.0
over(-3.020, blend(blend(uniform(-0.080, 6.148), blend(uniform(1.691, 6.439), uniform(-7.086, 2.158), uniform(3.423, 6.773)), uniform(-1.780, 2.381)), blend(uniform(-1.754, 1.943), uniform(-0.046, 6.327), blend(uniform(-6.667, 2.543), uniform(0.656, 7.903), blend(uniform(-8.673, 3.639), uniform(-7.606, 1.435), uniform(-5.138, -2.409)))), uniform(-8.008, -0.317))) -> 0.4487803553043079
Jawaban:
CJam, 58 byte
Ini adalah operator postfix yang bekerja pada stack:
2.0 1.0 3.0 U O
isover(2, uniform(1, 3))
.Jumlah skor
{[\]}
adalah fungsi itu sendiri,:U;
menugaskannya ke namaU
dan muncul. Pada dasarnya ini bukan bagian dari fungsi, jadi dengan aturan penghitungan skor 2, saya hanya perlu menghitung{[\]}
.B
didefinisikan dengan cara yang sama.Namun,
O
bersifat rekursif, dan jika saya tidak menentukan nama, tidak ada cara untuk mengulang. Jadi di sini, saya cenderung menghitung:O;
bagian. Maka skor saya adalah5+5+48=58
total byte.Penjelasan
U
muncul dua argumen dan membuat sepasang dalam urutan terbalik:a b => [b a]
.B
muncul tiga argumen dan membuat triple agar diputar:a b c => [b c a]
.O
Strukturnya adalah sebagai berikut:Subprogram Γ menangani distribusi seragam:
Subprogram Δ menangani distribusi campuran:
sumber
Ruby, 103
Mendefinisikan tiga lambdas,
u
,b
, dano
.u
dan masing-masingb
hanya membuat array dua elemen dan tiga elemen.o
mengasumsikan array dua elemen adalah distribusi yang seragam dan satu elemen tiga adalah campuran dari tiga distribusi. Dalam kasus terakhir ini menyebut dirinya secara rekursif.sumber
MATLAB, 73
Saatnya untuk sedikit "pemrograman fungsional" di MATLAB. Ini adalah 3 fungsi anonim. Seragam dan campuran disebut dengan cara yang sama seperti contoh, tetapi untuk
over
argumen harus ditukar. Saya tidak benar-benar membutuhkanover
sejak dua fungsi kembali yang pertama, tetapi sebagai formalitasfeval
adalah fungsi yang dapat memanggil fungsi.Sekarang sistem parsing dan evaluasi MATLAB sedikit sulit untuk sedikitnya. Itu tidak memungkinkan Anda untuk langsung memanggil fungsi yang dikembalikan dari suatu fungsi. Sebagai gantinya, seseorang harus terlebih dahulu menyimpan hasilnya ke variabel. Contoh ke-4 dapat dilakukan sebagai berikut:
Namun, dimungkinkan untuk menyiasatinya dengan menggunakan
feval
untuk memanggil semua fungsi. Jika definisi berikut digunakan, maka contoh-contohnya dapat dievaluasi persis seperti yang tertulis.sumber
Mathematica,
129116 byteu
,b
Dano
yanguniform
,blend
, danover
respectively.Wrapper alih fungsi standar. Ganti\uF3D2
s dengan karakter 3-byte. Hanya mengembalikan0
dan1
untuk kasus 1, 4, dan 7.sumber
Python, 146 byte
Strategi yang sama dengan jawaban Ruby histokrat, tetapi dengan Python. Untuk melakukan rekursi tanpa Z-combinator (yang akan mahal),
x
dany
didefinisikan sebagai fungsi pembantu yang mengevaluasiover
untuk tuple argumen 2 dan 3 panjang (uniform
danblend
argumen, masing-masing).Uji kasus pada ideone
sumber
Matlab, 104 byte
Saya harap ini masih valid, karena ini hanya berfungsi untuk distribusi dengan dukungan di [-10,10] yang merupakan persyaratan untuk bahasa yang tidak memiliki dukungan floating point. Vektor dukungan dan akurasi dapat dengan mudah disesuaikan dengan hanya mengubah angka yang sesuai.
u,o,b
adalah untukuniform,blend,over
. PDF hanya direpresentasikan sebagai vektor diskrit. Saya pikir pendekatan ini dapat dengan mudah ditransfer ke bahasa lain.Anda dapat mengujinya jika Anda mendefinisikan fungsi-fungsi itu terlebih dahulu dan kemudian tempelkan kode ini:
sumber
X
danD
denganMIN_FLOAT
danMAX_FLOAT
(atau apa pun Matlab memanggil mereka), maka ini adalah pendekatan yang valid.realmax
/realmin
, Anda bahkan bisa membuat vektor yang masuk ke semua nomor floating point jika Anda memiliki cukup memori.