Saya membaca tentang lingkaran di suatu tempat, dan baru saja belajar tentang cakram ( itu sebenarnya konsep yang cukup umum ) dan berpikir tentang codegolf.
Tugas Anda adalah untuk mengacak satu titik / beberapa titik pada disk dengan jari-jari 1.
Aturan:
- Semua poin harus memiliki probabilitas yang sama untuk dihasilkan
- Koordinat titik apung harus digunakan; persyaratan minimum adalah dua desimal (misalnya poin
(0.12, -0.45)
atau(0.00, -1.00)
valid) - Anda mendapatkan -20 byte jika program Anda benar-benar menampilkan lingkaran pembatas dan titik yang dihasilkan di dalamnya. Koordinat masih harus valid tetapi tidak ditampilkan, dan gambar yang dihasilkan harus berukuran paling tidak 201 x 201 piksel
- Anda mendapatkan -5 byte jika program Anda mengambil jumlah poin yang akan dihasilkan sebagai input pada stdin
- Jika Anda memutuskan untuk tidak memplot lingkaran pembatas dan titik, program Anda harus menampilkan titik yang dihasilkan pada format
(x, y)
atau(x,y)
pada stdout - Jika Anda memutuskan untuk mengambil jumlah titik yang dihasilkan sebagai input, tetapi tidak untuk memplotnya - program Anda harus menampilkan semua titik acak pada format yang disebutkan di atas dengan atau tanpa satu ruang di antaranya.
Pengajuan terpendek dalam byte menang!
code-golf
math
graphical-output
random
sweerpotato
sumber
sumber
0.3503082505747327+0.13499221288682994j
.Jawaban:
Pyth, 26 - 5 = 21 byte
Mengambil jumlah koordinat untuk dihasilkan pada stdin, dan mengeluarkannya pada stdout seperti:
Menggunakan strategi yang mirip dengan @ MartinBüttner, menghasilkan koordinat kutub dan jari-jari, kecuali itu menggunakan eksponensial kompleks.
sumber
p
, bukan? Itu hanya mengubah output ke baris yang terpisah.CJam,
2827 byteSolusi ini bukan berbasis penolakan. Saya menghasilkan titik dalam koordinat kutub, tetapi dengan distribusi yang tidak seragam dari jari-jari untuk mencapai kerapatan titik yang seragam.
Uji di sini.
Penjelasan
Mengapa ini berhasil? Pertimbangkan anulus jari-jari sempit
r
dan lebar (kecil)dr
. Daerah tersebut kira-kira2π*r*dr
(jika annulus sempit, keliling bagian dalam dan luar hampir identik, dan kelengkungan dapat diabaikan, sehingga daerah tersebut dapat diperlakukan sebagai bidang segi empat dengan panjang sisi keliling dan lebar kelengkungan). annulus). Jadi area bertambah secara linear dengan jari-jari. Ini berarti bahwa kami juga menginginkan distribusi linear dari jari-jari acak, untuk mencapai kerapatan konstan (pada radius dua kali, ada area dua kali lebih banyak untuk diisi, jadi kami ingin dua kali lebih banyak titik di sana).Bagaimana kita menghasilkan distribusi acak linier dari 0 ke 1? Mari kita lihat kasus diskritnya terlebih dahulu. Katakanlah, kami memiliki distribusi yang diinginkan dari 4 nilai, seperti
{0.1, 0.4, 0.2, 0.3}
(yaitu kami ingin1
menjadi 4 kali lebih umum0
, dan dua kali lebih umum2
; kami ingin3
tiga kali lebih umum0
):Bagaimana cara memilih satu dari empat nilai dengan distribusi yang diinginkan? Kita dapat menumpuknya, mengambil nilai acak seragam antara 0 dan 1 pada sumbu y dan memilih segmen pada titik itu:
Ada cara berbeda untuk memvisualisasikan pemilihan ini. Sebagai gantinya, kami dapat mengganti setiap nilai distribusi dengan akumulasi nilai hingga saat itu:
Dan sekarang kita memperlakukan baris teratas dari bagan ini sebagai fungsi
f(x) = y
dan membalikkannya untuk mendapatkan fungsi , yang dapat kita terapkan pada nilai acak seragam di :g(y) = f-1(y) = x
y ∈ [0,1]
Keren, jadi bagaimana memanfaatkan ini untuk menghasilkan distribusi linear jari-jari? Ini adalah distribusi yang kami inginkan:
Langkah pertama adalah mengakumulasi nilai-nilai distribusi. Tetapi distribusi ini kontinu, jadi alih-alih menjumlahkan semua nilai sebelumnya, kami mengambil integral dari
0
ker
. Kita dapat dengan mudah memecahkan analitis bahwa: . Namun, kami ingin ini dinormalisasi, yaitu untuk mengalikannya dengan konstanta sehingga memberikan nilai maksimum , jadi yang benar-benar kita inginkan adalah :∫0r r dr = 1/2 r2
1
r
r2
Dan akhirnya, kita membalikkan ini untuk mendapatkan fungsi yang dapat kita terapkan pada nilai yang seragam
[0,1]
, yang dapat kita lakukan lagi secara analitis: hanya sajar = √y
, di manay
adalah nilai acak:Ini adalah teknik yang cukup berguna yang sering dapat digunakan untuk menghasilkan distribusi sederhana dengan tepat (ini berfungsi untuk distribusi apa pun, tetapi untuk yang rumit, dua langkah terakhir mungkin harus diselesaikan secara numerik). Namun, saya tidak akan menggunakannya dalam kasus khusus ini dalam kode produksi, karena akar kuadrat, sinus dan kosinus sangat mahal: menggunakan algoritma berbasis penolakan rata-rata jauh lebih cepat, karena hanya membutuhkan penambahan dan perkalian.
sumber
Mathematica,
6844 - 20 = 24 byteTerima kasih banyak untuk David Carraher karena memberi tahu saya
RandomPoint
, yang menyelamatkan 24 (!) Byte. Mathematica memang memiliki built-in untuk semuanya.Ini menentukan titik dan lingkaran terikat untuk memenuhi syarat untuk bonus:
Hasilnya adalah gambar vektor, sehingga spesifikasi ukuran 201x201 piksel tidak benar-benar masuk akal, tetapi secara default itu membuat lebih besar dari itu.
sumber
Graphics[{Circle[], Point@RandomPoint@Disk[]}]
?Graphics@{Circle[], Point@RandomPoint@Disk[]}
,
?CJam,
3126 byteIni berfungsi dengan berulang kali menghasilkan titik acak dalam kuadrat panjang sisi 2 dan menjaga titik pertama yang berada di dalam disk unit.
Terima kasih kepada @ MartinBüttner untuk bermain golf 3 byte!
Cobalah online di penerjemah CJam .
Bagaimana itu bekerja
sumber
iKe ,
5351 byteTidak ada yang istimewa, tapi saya kira kita harus memiliki setidaknya satu solusi grafis:
Cobalah di browser Anda .
Sunting: Saya dapat memotong dua byte dengan menerapkan pendekatan @ MartinBüttner untuk memodifikasi distribusi koordinat kutub. Saya pikir ini juga sedikit lebih langsung:
sumber
Perl, 59 Bytes
Ini hanyalah solusi sederhana, menghasilkan poin dalam kotak dan menolak yang terlalu jauh. Trik golf tunggal saya adalah memasukkan tugas di dalam kondisi.
Sunting: Dalam proses bermain golf, saya menemukan cara yang menarik untuk mencetak poin acak pada sebuah lingkaran .
sumber
Oktaf,
2453 - 20 = 33 byteMenghasilkan 501 nilai theta dengan jarak yang sama ditambah satu angka acak dan menskalakan semuanya menjadi [0..2π]. Kemudian menghasilkan 501 1 untuk jari-jari lingkaran, ditambah jari-jari acak untuk titik dan mengambil akar kuadrat untuk memastikan distribusi seragam pada disk. Kemudian plot semua titik sebagai koordinat polar.
Berikut ini adalah demonstrasi cepat distribusi (tanpa lingkaran unit):
sumber
Oktaf / Matlab,
7464 byteMetode penolakan , 64 byte:
Metode langsung , 74 byte (terima kasih kepada Martin Büttner karena membantu saya memperbaiki dua kesalahan):
sumber
R,
999581-20 =797561 BytesGunakan konstruksi bilangan kompleks untuk membangun x / y dari koordinat kutub. Mengambil input agak mahal dan mungkin ada cara yang lebih baik untuk melakukan ini. The
ylim
danadalah untuk memastikan seluruh lingkaran diplot danxlim
asp
tanda titik ditampilkan di bawah simbol lingkaran.Terima kasih kepada @jbaums dan @flodel untuk penghematannya
Coba di sini
sumber
runif(9,0,1)
dapat disederhanakan menjadirunif(9)
symbols(0,0,1,i=F,asp=1,ylim=c(-1,1));points(complex(,,,runif(9),runif(9,-1)*pi))
yli
bekerja di tempatylim
.Memproses / Java 141 byte-20 = 121
persyaratan untuk 201 * 201 sebagai ukuran minimum mengharuskan saya untuk memasukkan
setup
metode sejak Processing.org default ke 200x200 :(sumber
QBasic, 138 byte - 20 - 5 = 113
Mengambil input pengguna dan menggambar disk dan poin. Diuji pada QB64 .
Ini adalah strategi "lempar ke papan dart dan simpan tongkat apa yang cukup mendasar". Tangkapannya adalah bahwa "tongkat apa" tidak ditentukan secara matematis tetapi secara grafis: cakram putih diplot pada latar belakang hitam, dan kemudian titik-titik yang dihasilkan secara acak ditolak sampai tidak hitam. Poin-poin itu sendiri digambar dengan warna biru (meskipun sulit untuk mengetahui kapan mereka memiliki piksel tunggal - klik pada gambar untuk memperbesar).
sumber
awk - 95 - 5 = 90
Karena saya tidak begitu yakin tentang rand () <. 5 bagian, saya melakukan beberapa pengujian distribusi dengan ini, menggunakan skrip ini:
yang untuk input 1e7 memberi saya hasil ini, setelah saya menyesap kopi sekali atau dua kali:
yang menurut saya cukup baik.
Penjelasan kecil:
Setelah menulis sebentar ternyata, jika Anda ingin membagi disk menjadi empat cincin dengan luas yang sama, jari-jari di mana Anda harus memotong adalah sqrt (1/4), sqrt (1/2) ) dan sqrt (3/4). Karena jari-jari aktual dari pengujian titik saya adalah sqrt (x ^ 2 + y ^ 2), saya dapat melewatkan rooting persegi secara bersamaan. "Kebetulan" 1/4, 2/4, 3/4 mungkin terkait dengan apa yang ditunjukkan M. Buettner sebelumnya.
sumber
HPPPL , 146 (171-20-5) byte
Contoh untuk 10000 poin (termasuk penghitungan waktu dalam detik untuk perangkat nyata):
Fungsi itu sendiri dipanggil oleh
r(n)
. Sisanya pada gambar di atas hanya untuk tujuan pengaturan waktu.Hasil (diameter disk adalah 236 piksel):
Versi di atas tidak menyimpan titik koordinat, jadi saya menulis versi yang mengambil dua parameter
r(n,p)
.n
adalah jumlah poin danp=0
mengembalikan poin ke terminal,p=1
plot poin dan disk), dalam kasus menyimpan koordinat adalah wajib. Versi ini panjangnya 283 (308-20-5) byte:Versi ungolfed:
Output terminal untuk
r(10,0)
:r(10,1)
menunjukkan disk dengan titik-titik, seperti yang ditunjukkan di atas.sumber
JavaScript, 75 byte
Berbasis penolakan:
Metode langsung (80 byte):
sumber
Python,
135130 byteMenghapus
**0.5
terima kasih atas saran @ jimmy23013 (karena ini adalah lingkaran satuan, saya sekarang memeriksa apakah jarak kuadrat antara (x, y) dan (0, 0) sama dengan 1 2. Ini adalah hal yang sama).Ini juga membebaskan saya untuk menghapus tanda kurung.
sumber
**0.5
.