Cara menentukan generasi acak dalam tantangan

16

Catatan : Sesuai konsensus di Meta , pertanyaan ada di topik di sini.

Mengingat "hal yang harus dihindari ketika menulis tantangan" , saya mulai berpikir tentang tantangan yang melibatkan generasi acak dari jenis objek tertentu.

Terkadang saya ingin memposting tantangan yang melibatkan pembuatan foo secara acak, di mana

  1. sangat mudah untuk memeriksa apakah sesuatu yang diberikan adalah foo, dan
  2. sedikit lebih sulit untuk secara cepat menghasilkan foo acak "berkualitas baik".

Sebagai contoh, foo mungkin berupa matriks biner di mana tidak ada segmen dengan 4 bit yang sama ke segala arah. Sangat mudah untuk memeriksa apakah matriks biner yang diberikan adalah foo, tetapi menghasilkan foo acak dengan distribusi yang tersebar nampaknya membutuhkan algoritma penelusuran ulang atau sesuatu yang serupa.

Ngomong-ngomong, sekarang saya harus menentukan secara objektif apa yang memenuhi syarat sebagai foo acak, dan saya ingin itu "tidak dapat diprediksi" dalam arti intuitif bahwa ketika saya menjalankan program beberapa kali, hasilnya selalu terlihat berbeda. Pendekatan yang paling restriktif adalah mensyaratkan bahwa outputnya acak acak: semua foo yang valid memiliki kemungkinan yang sama untuk dihasilkan. Ini biasanya terlalu membatasi, karena saya tidak tahu bagaimana cara menyimpannya untuk menghasilkan semua foo yang valid, menghapus duplikat dan memilih satu, yang membosankan dan lambat.

Ide saya berikutnya adalah mengharuskan semua foos yang valid memiliki kemungkinan positif untuk dihasilkan. Namun, ini berarti bahwa pendekatan berikut ini valid: menghasilkan hal seperti foo acak (dalam contoh kami, matriks biner acak), jika itu foo lalu kembalikan, jika tidak kembalikan foo kode keras (katakanlah, matriks identitas ). Ini juga agak membosankan, karena itu pada dasarnya hanya sebuah pengenalan foo ditempelkan ke generator matriks acak.

Mungkinkah ada definisi umum yang bagus untuk foo acak yang tidak terduga?

TL; DR

Apakah ada cara yang baik untuk menentukan objek yang dihasilkan secara acak yang "tidak dapat diprediksi" yang tidak memperbaiki distribusi tetapi tidak mendukung pengkodean keras?

Zgarb
sumber
Kami memiliki definisi standar untuk acak pada meta yang akan melarang pengkodean-keras, tetapi tidak membatasi sejauh seragam sempurna.
Geobit
5
Pertanyaan bagus Saya telah menemukan di masa lalu bahwa menentukan keacakan itu sulit . Khusus untuk skenario yang Anda gambarkan, ada juga masalah yang bisa Anda buat hanya kandidat acak dan ulang jika mereka tidak valid. Itu bahkan memberi Anda distribusi seragam, tetapi runtime non-deterministik. Ketika menentukan distribusi seragam ada juga masalah bahwa solusi nyata tidak pernah seragam sempurna . Ini adalah masalah yang sangat halus. +1
Martin Ender
@ MartinEnder Benar, saya lupa pendekatan itu. Saya dapat melarangnya dan algoritma lambat lainnya dengan batas waktu, tetapi mereka masih memungkinkan solusi "satu hard-coded foo".
Zgarb
sepertinya Anda dapat menentukan K3 / K4 CPRNG, sebagian besar bahasa akan memiliki perpustakaan en.wikipedia.org/wiki/Pseudorandom_number_generator
Ewan
1
@Zgarb masalah besar dengan pelarangan "Hasilkan dan ulang" adalah bahwa sebagian besar perpustakaan RNG bahasa melakukan hal itu.
Nathan Merrill

Jawaban:

5

Kembalikan seribu foo yang berbeda

Ini membuatnya tidak mungkin untuk mengembalikan nilai-nilai hardcoded dan memiliki golf yang layak. Namun, generator foo yang sah memiliki peluang kecil untuk menghasilkan duplikat foo kecuali jika benar-benar memeriksa mereka. Untuk menghilangkan beban pemeriksaan, tingkat kegagalan yang diuji secara empiris, katakanlah 10%, dapat ditetapkan sebagai dapat diterima.

Waspadai paradoks ulang tahun , bahwa kemungkinan duplikat mungkin lebih tinggi dari yang Anda pikirkan. Jika hanya ada satu juta foo yang mungkin, seribu foo acak akan memiliki probabilitas sekitar 0,6 bahwa ada duplikat di sana di suatu tempat, dan itu mengasumsikan bahwa generasi foo benar-benar seragam. Jika ini bisa menjadi masalah, perlu katakan 900 foo unik untuk setiap 1000 yang dihasilkan, yang jauh lebih murah untuk generator foo asli tetapi masih tidak praktis untuk hardcoding.

Ini juga memungkinkan Anda untuk berulang kali menghasilkan hal-hal seperti foo dan memeriksa fooness sampai Anda mendapatkan foos. Saya pikir ini adalah solusi yang valid sendiri, tetapi jika Anda tidak menyukainya:

Lakukan dengan cepat

Peluang untuk hal-hal seperti foo yang benar-benar acak menjadi foo mungkin cukup rendah, sehingga menentukan batas waktu kemungkinan akan memaksa upaya asli pada generasi foo.

Untuk mengakomodasi perbedaan kecepatan antara bahasa yang berbeda, Anda mungkin ingin memiliki batas waktu yang berbeda tergantung pada bahasa seperti Hackerrank: https://www.hackerrank.com/environment . Namun, jika Anda menentukan foo yang cukup besar, kemungkinan foo-like foo-like foo mungkin sangat rendah, sehingga aturan "sebelum kematian panas Semesta" mungkin cukup.

James Hollis
sumber
Saya pikir Anda ke sesuatu di sini. "Menjalankan program N kali tidak akan menghasilkan duplikat setidaknya 90% dari waktu" adalah konkret dan cukup mudah untuk diuji, dan dapat dikombinasikan dengan batas waktu untuk mencegah pemaksaan kasar dan pengambilan sampel penolakan sederhana juga.
Zgarb
2

Saya tidak mengklaim memiliki solusi akhir untuk masalah ini (atau bahwa daftar ini lengkap), tetapi saya ingin menguraikan beberapa pendekatan yang mungkin muncul dalam pikiran dan mengapa mereka mau atau tidak berhasil. Saya juga tidak akan membahas masalah tangensial seperti apakah menggunakan stempel waktu saat ini sebagai sumber keacakan cukup "tidak dapat diprediksi" dan bagaimana menegakkan properti tertentu dari distribusi probabilitas - saya hanya akan fokus pada menghindari solusi yang menggunakan hardcoding.

Bukan solusi: melarang hard-coding secara eksplisit

Ini ide yang buruk. Ini adalah persyaratan yang tidak dapat diobservasi (yang berarti Anda tidak dapat menentukan apakah itu puas hanya dengan menjalankan program), yang sangat tidak disarankan di PPCG dan mungkin sama sekali tidak mungkin jika menjalankan program pada platform lain, di mana pengiriman diverifikasi dalam suatu cara otomatis. Masalah dengan persyaratan seperti ini adalah Anda harus mulai dengan menemukan definisi objektif untuk "hard-coding". Secara umum, jika Anda mencoba ini, Anda hanya akan memperburuk keadaan.

Membuat hard-coding tidak mungkin

Jika Anda tidak dapat sepenuhnya melarangnya, tetapi Anda tidak ingin orang menggunakannya, maka Anda dapat mencoba merancang tantangan sedemikian rupa sehingga hard-coding sama sekali bukan pendekatan kompetitif. Ini dimungkinkan jika objek yang harus dihasilkan cukup besar dan tidak dapat dimampatkan sehingga memasukkan satu contoh ke dalam kode akan membutuhkan lebih banyak byte daripada menulis algoritma yang menghasilkan solusi yang valid secara acak. Dalam contoh spesifik Anda, tentu saja bukan itu masalahnya, karena matriks identitas valid dan umumnya mudah dibuat, tetapi untuk masalah lain, mungkin bukan itu masalahnya. Jika objek target cukup tidak beraturan, cukup minta mereka berukuran besar, yang mungkin tidak akan memengaruhi jumlah byte dari algoritma aktual tetapi akan meledakkan bagian hard-coded.

Parameterkan output

Seringkali, masalah ini datang dengan satu atau lebih parameter alami, seperti ukuran matriks pada contoh Anda. Jika demikian, menjadikan parameter itu input yang cukup untuk membuat hard-coding tidak mungkin atau setidaknya tidak praktis. Dalam beberapa kasus, mungkin sulit untuk membuat kode satu solusi spesifik untuk nilai parameter tertentu yang telah ditemukan secara manual atau melalui pencarian ekstensif, tetapi mungkin tidak ada formulir tertutup sederhana untuk instance dari solusi ini secara umum, jadi tidak mungkin untuk menghasilkan nilai default untuk input sewenang-wenang dengan mudah. Sekali lagi, ini bukan kasus untuk contoh yang Anda sebutkan, karena matriks identitas bekerja pada ukuran berapa pun, tetapi solusi optimal untuk masalah terkait inibiasanya sangat tidak teratur, jadi tidak mungkin untuk memiliki nilai default tanpa tetap mencari nilai yang valid. Anda dapat menggabungkan ini dengan batas waktu untuk menghindari pencarian brute force untuk nilai default.

Masukan beberapa pembatasan distribusi probabilitas

Jika Anda bersedia menyerahkan distribusi probabilitas yang sepenuhnya tidak dibatasi, Anda dapat menempatkan beberapa kendala padanya, yang masih memberi banyak kebebasan kepada penjawab dalam memilih distribusi mereka tetapi yang membuat hard-coding menjadi sulit atau tidak mungkin:

  • Kendala paling sederhana yang muncul dalam pikiran adalah untuk memerlukan perbedaan antara probabilitas minimum dan maksimum untuk setiap output yang mungkin berada di bawah ambang tertentu. Pendekatan hard-code kemungkinan akan memiliki probabilitas hampir nol untuk hampir semua output dan probabilitas mendekati 1 untuk nilai default. Jika Anda memerlukan perbedaan maksimum di bawah 0,1 katakan, akan perlu ada 10 (nilai acak) untuk membuat pendekatan opsi. Demikian pula Anda juga bisa hanya memerlukan probabilitas minimum untuk setiap output yang mungkin, misalnya 1 / (2 * N *), di mana N adalah jumlah output yang mungkin.
  • Sebagai alternatif, Anda dapat mensyaratkan bahwa tidak ada (kemungkinan) kesenjangan dalam distribusi, sehingga tidak ada interval ukuran δ (dipilih oleh Anda) sedemikian rupa sehingga ada probabilitas lebih tinggi dan lebih rendah. Itu berarti tidak mungkin ada outlier dalam hal kemungkinan, yang kemungkinan dihasilkan oleh pendekatan hard-coding.

Masalah utama dengan pendekatan ini adalah bahwa mereka jauh lebih sulit untuk dipikirkan, membuktikan kebenaran jawaban itu sulit, dan secara eksperimental memverifikasi kebenaran bisa mustahil untuk ruang output yang besar. Namun, mereka memberikan persyaratan yang pada dasarnya dapat diamati untuk program yang dapat membuat hardcoding tidak mungkin.

Pendekatan-pendekatan ini mungkin juga memerlukan batas waktu, karena salah satu cara untuk meningkatkan probabilitas nilai-nilai non-standar adalah dengan mencoba menemukan foo acak beberapa kali sebelum jatuh kembali ke nilai default.

Martin Ender
sumber