Tugas
Diberikan bilangan bulat positif n
kurang dari yang 2^30
ditentukan sebagai input dengan cara apa pun yang Anda pilih, kode Anda harus menghasilkan bilangan bulat acak antara 0
dan n
, termasuk. Angka yang Anda hasilkan harus dipilih secara acak . Itu adalah setiap nilai dari 0
hingga n
harus terjadi dengan probabilitas yang sama (lihat Aturan dan Peringatan).
Aturan dan Peringatan
Kode Anda dapat mengasumsikan bahwa setiap generator angka acak yang dibangun ke dalam bahasa Anda atau pustaka standar yang mengklaimnya acak secara acak sebenarnya seragam. Itu adalah Anda tidak perlu khawatir tentang kualitas sumber acak yang Anda gunakan. Namun,
- Anda harus menetapkan bahwa jika sumber acak yang Anda gunakan adalah seragam maka kode Anda dengan benar menghasilkan integer acak seragam dari
0
ken
. - Argumen apa pun saat memanggil fungsi bawaan atau pustaka acak harus konstan. Itu mereka harus sepenuhnya independen dari nilai input.
- Kode Anda dapat berakhir dengan probabilitas 1 daripada dijamin untuk berakhir.
Catatan
randInt(0,n)
tidak valid karena mengambil input sebagai argumen ke fungsi builtin atau library.rand()%n
tidak akan memberikan nomor acak seragam pada umumnya. Sebagai contoh yang diberikan oleh betseg, jikaintmax == 15
dann = 10
, maka Anda akan jauh lebih mungkin mendapatkan0-5
daripada6-10
.floor(randomfloat()*(n+1))
juga tidak akan memberikan angka acak seragam pada umumnya karena jumlah terbatas dari nilai floating point yang mungkin antara 0 dan 1.
code-golf
number
random
probability-theory
benar-benar manusiawi
sumber
sumber
rng()
memberikan0
-100
, jikan = 75
, dan fungsinya adalahrng()%75
, maka 0-25 akan lebih umum ...)Jawaban:
mesin x86 dengan
rdrand
instruksi, 10 bytekode mesin
Input ada di register
rdi
dan output dirax
.Ini menghormati SYS V AMD64 ABI sehingga kode secara efektif mengimplementasikan fungsi C
dengan int 32-bit.
Instruksi
rdrand
dijelaskan oleh IntelBerhubungan dengan CSRNG, implisit bahwa distribusinya seragam, mengutip NIST SP 800-90A:
Prosedur ini menghasilkan angka acak dan jika tidak benar-benar lebih besar dari input itu dikembalikan.
Jika tidak, proses akan diulangi lagi.
Karena
eax
32-bit,rdrand
mengembalikan angka antara 0 dan 2 32 -1, jadi untuk setiap n di [0, 2 32 -1] jumlah iterasi yang diharapkan adalah 2 32 / (n + 1) yang didefinisikan untuk semua n dalam [0, 2 30 ).sumber
jnc
?rdrand
menetapkan bahwaCF
jika data yang dikembalikan valid. Data mungkin tidak valid karena terlalu banyak permintaan mengeringkan kumpulan entropi. Lihat entri manual untuk rdrand dan ini .Jelly ,
76 byteTerima kasih kepada @JonathanAllan untuk bermain golf 1 byte!
Tidak dapat dijalankan di TIO karena (16!)! adalah jumlah yang sangat besar .
Bagaimana itu bekerja
sumber
Mathematica, 29 byte
Berdasarkan jawaban Dennis's Jelly .
Saya tidak akan merekomendasikan untuk menjalankan ini.
2e9!
adalah jumlah yang cukup besar ...Ternyata menjadi yang terpendek untuk menghasilkan sejumlah besar yang dapat dibagi oleh semua input yang mungkin dan memetakan hasilnya ke kisaran yang diperlukan dengan modulo sederhana.
Sampel Penolakan, 34 byte
Pendekatan lama saya yang menghasilkan kode yang lebih menarik:
Pengambilan sampel penolakan dasar. Kami menginisialisasi output ke 13! (yang lebih besar dari input maksimum 2 30 ) dan kemudian menggantinya berulang kali dengan integer acak antara 0 dan 13! asalkan nilainya lebih besar dari input.
sumber
Brachylog , 9 byte
Cobalah online!
Ini menggunakan
13!
seperti dalam jawaban Martin Ender (13ḟ
kurang dari satu byte2^₃₀
).ṙ
diimplementasikan menggunakanrandom_between/3
, yang, ketika menggali sumbernya, menggunakanrandom_float/0
yang terkait denganrandom/1
yang menggunakan algoritma Mersenne Twister yang seragam untuk tujuan kami.Penjelasan
sumber
Prolog (SWI) , 38 byte
Bekerja dengan sampel penolakan.
Hasilkan angka acak antara 0 dan 2 ^ 31-1 = 2147483647 hingga ditemukan kurang dari atau sama dengan input.
Saya merasa seolah-olah saya bisa menggunakan potongan daripada yang lain, tapi saya tidak bisa melihat caranya.
sumber
repeat
, tetapi akhirnya menjadi 3 byte lebih lama ... Saya tidak yakin apakah ada cara yang lebih pendek untuk memiliki poin pilihan yang tak terbatas daripada mengulang.,!.
untuk memaksa mundur, tetapi entah saya salah mengingatnya atau itu tidak berlaku untuk solusi ini.Labirin , 63 byte
(Terima kasih kepada @MartinEnder untuk bantuan bermain golf berat di sini.)
Labyrinth adalah bahasa 2D, dan satu-satunya sumber keacakan dalam situasi seperti berikut:
Asumsikan pointer instruksi ada di
x
dan bergerak ke bawah. Selanjutnya mendarat di<
, yang jika bagian atas tumpukan adalah 0 (yang selalu terjadi dalam program aktual di atas) menggeser baris saat ini ditinggalkan oleh 1:Penunjuk instruksi sekarang
<
bergerak ke bawah. Di persimpangan, Labyrinth belok berdasarkan bagian atas tumpukan - negatif belok kiri, positif belok kanan dan nol bergerak maju. Jika bagian atas tumpukan masih nol pada titik ini, kita tidak dapat bergerak maju atau mundur karena tidak ada jalur, sehingga Labirin akan mengacak antara belok kiri atau belok kanan dengan probabilitas yang sama.Pada dasarnya apa yang dilakukan oleh program di atas adalah menggunakan fitur keacakan untuk menghasilkan angka 100-bit (100 ditentukan di
#00
sini) dan melanjutkan perulangan hingga menghasilkan angka<= n
.Untuk pengujian, mungkin akan lebih baik digunakan
#0"
untuk angka 10-bit, dengan"
menjadi jalur no-op. Cobalah online!Penjelasan kasar:
sumber
Python, 61 byte
Sunting: Diperbarui untuk menghindari formulir terlarang
Sunting2: Disimpan 2 byte, terima kasih @ JonathanAllan
Sunting3: Dibayar 2 byte untuk solusi yang berfungsi penuh - terima kasih lagi @JonathanAllan
Sunting4: Dihapus
f=
, menyimpan 2 byteSunting5: Disimpan 1 byte lebih banyak berkat @ JonathanAllan
Sunting6: Disimpan 2 byte lebih banyak berkat @ JonathanAllan
Sekarang, git menyalahkan akan menunjuk pada saya untuk hal-hal buruk, dan Jonathan Allan untuk hal-hal yang membantu.
Sunting7: Saat hujan, itu menuangkan - 2 byte lagi
Sunting8: Dan 2 byte lagi
sumber
n
, tetapi Anda dapat menyimpan dua byte saat Anda memperbaikinya dengan menggunakanfrom random import*
dan menjatuhkanr.
....*(-~n*1.0/2**30))
daripada...*((n+1)*1.0/2**30))
randrange
tampaknya menerima float, jadilambda n,x=2.**30:int(randrange(x)*-~n/x)
simpan dua [edit ...] empat!Python 2 , 61 byte
Pseudo-acak memilih integer antara 0 dan k untuk semua nilai k antara 0 dan 2 31 - 2 , kemudian mengambil integer yang sesuai dengan k = n .
sumber
Batch, 64 byte
%random%
hanya memberikan 15 bit keacakan, jadi saya harus menggabungkan dua angka acak. Putaran sampai nilai acak berada dalam kisaran yang diinginkan, jadi lambat untuk rendahn
; 98 byte untuk versi yang lebih cepat:sumber
n
?call
, menjalankan skrip batch akan menghentikan skrip saat ini.MATL , 12 byte
Terima kasih kepada @AdmBorkBork dan @Suever karena memberi tahu saya cara menonaktifkan cache TIO.
Cobalah online! .
Ini menggunakan metode penolakan : menghasilkan bilangan bulat acak dari
0
ke2^30-1
, dan ulangi saat melebihi inputn
. Ini dijamin untuk berakhir dengan probabilitas1
, tetapi jumlah rata-rata iterasi adalah2^30/n
, dan karena itu sangat lama untukn
secara signifikan lebih kecil daripada2^30
.sumber
JavaScript (ES6),
5554 byteMenghasilkan bilangan bulat dalam kisaran [0 ... 2 k - 1] , di mana k adalah bilangan bulat terkecil sehingga 2 k lebih besar dari n . Ulangi sampai hasilnya jatuh ke [0 ... n] .
Mengapa?
Ini didasarkan pada asumsi berikut:
Secara internal, nilai integer pseudo-acak yang dihasilkan oleh mesin JS untuk memberi makan
Math.random()
seragam pada setiap interval [0 ... 2 k -1] (dengan k <32 ).Setelah dikalikan dengan kekuatan tepat 2, nilai float IEEE 754 yang dikembalikan oleh
Math.random()
masih seragam selama interval tersebut.Jika ada yang bisa mengkonfirmasi atau membantah hipotesis ini, beri tahu saya di komentar.
Demo
Menghasilkan 1 juta nilai dalam [0 ... 2] dan menampilkan statistik hasil.
Tampilkan cuplikan kode
sumber
Bash (+ coreutils), 44 byte
/ dev / solusi berbasis urandom
Akan membaca bilangan bulat 32 bit yang tidak ditandatangani dari
/dev/urandom
, dan menyaringnyaawk
sampai menemukan satu dalam kisaran yang diberikan, kemudiansed q
akan membatalkan pipa.sumber
Haskell, 70 byte
Bukan algoritma yang sangat efisien tetapi berhasil. Ini menghasilkan daftar bilangan bulat tak terbatas (atau mengapung jika diperlukan, karena sistem tipe Haskell) yang dibatasi oleh [0,2 ^ 30] dan mengambil yang pertama kurang dari atau sama dengan n. Untuk kecil dan ini bisa memakan waktu lama. Angka-angka acak harus didistribusikan secara seragam, seperti yang ditentukan dalam dokumentasi untuk randomR sehingga semua angka dalam interval [0,2 ^ 30] harus memiliki probabilitas yang sama (1 / (2 ^ 30 + 1)) karena itu semua angka dalam [ 0, n] memiliki probabilitas yang sama.
Versi Alternatif:
Versi ini mengerikan tetapi menyimpan seluruh byte.
randoms
menggunakan rentang sewenang-wenang yang ditentukan oleh tipe untuk menghasilkan daftar angka yang tak terbatas. Ini mungkin termasuk negatif sehingga kita perlu memetakannyaabs
untuk memaksa mereka positif (atau nol). Ini sangat lambat untuk nilai n yang tidak terlalu besar. EDIT : Saya menyadari kemudian bahwa versi ini tidak terdistribusi secara seragam karena kemungkinan mendapatkan 0 lebih buruk daripada angka-angka lain karena penggunaanabs
. Untuk menghasilkan beberapa angkam
, generator dapat menghasilkanm
atau-m
tetapi dalam kasus 0 hanya 0 itu sendiri yang akan bekerja, oleh karena itu probabilitasnya adalah setengah dari angka lainnya.sumber
Jelly , 9 byte
Cobalah online! - kode di atas tidak akan berjalan pada TIO karena kisaran ukuran 16! harus dibangun terlebih dahulu (belum lagi fakta bahwa mereka kemudian perlu dikocok dan kemudian disaring!), jadi ini adalah hal yang sama pada skala yang jauh lebih kecil, diulang 30 kali untuk input 3 dengan batas 10.
Bagaimana?
Catatan: akan lebih dari seribu kali lebih efisien untuk jumlah byte yang sama jika
ȷ⁵
melakukan apa yang diharapkan secara naif dan mengembalikan sepuluh ke sepuluh, tetapi itu tidak terjadi karena⁵
tidak dievaluasi sebagai sepuluh literal yang akan digunakan dengan angka literalȷ...
tetapi lebih dari dua literal yang terpisah diurai,ȷ
dengan eksponen default tiga menghasilkan seribu, dan⁵
menghasilkan sepuluh.sumber
JDK 9 on jshell,
7559 bytePemakaian
OptionalInt
. Aturan tidak menentukan bahwa tipe pengembalian harus primitif dan saya mempertimbangkanOptionalInt
untuk menjadi representasi hasil yang valid.sumber
Optional
diterima. Saya akan mengkonfirmasi dengan poster jika saya adalah Anda. Juga, tidak perlu menghitung seluruh penugasan; hanya ungkapan lambda yang cukup.n
dannew Random()
.PHP, 30 byte
Jalankan dengan
echo <N> | php -Rn '<code>'
.mengambil nomor acak antara 0 dan
getrandmax()
(2 ** 31-1 pada mesin 64 bit saya);ulangi sementara itu lebih besar dari input.
Ini mungkin membutuhkan waktu ... AMD C-50 (1 GHz) saya dibutuhkan antara 0,3 dan 130 detik untuk
N=15
.Cara yang lebih cepat untuk rata-rata
N
( 46 byte ):atau
mengambil
N+1
bilangan bulat acak, menjumlahkannya dan mengambil modulo dengannyaN+1
.C-50 membutuhkan sekitar. 8 detik untuk 1 juta putaran.
Solusi yang tidak valid untuk 19 byte :
sumber
PowerShell , 35 byte
Cobalah online!
Metode pengambilan sampel penolakan lainnya. Ini adalah
for
loop tak terbatas , menetapkan nilai$a
menjadiRandom
bilangan bulat antara0
dan1gb
(= 1073741824 = 2^30
), dan terus berulang sepanjang bilangan bulat itu-g
reatert
dari input$args
. Setelah loop selesai, kita tinggal memasang$a
pipeline dan outputnya implisit.Catatan: Ini akan memakan waktu lama jika inputnya sedikit.
sumber
Python 2 ,
7269 byte-3 bytes berkat xnor (menimpa bawaan
id
sebagai variabel)Cobalah online!
randrange(2**30)
menghasilkan angka didistribusikan semu-seragam (Mersenne Twister 2 19937-1 ) dari kisaran [0,2 30 ) . Karenan
dijamin berada di bawah 2 30 ini dapat dengan mudah dipanggil berulang kali hingga tidak lebih besar dari input. Diperlukan waktu yang lama untuk nilai yang sangat rendahn
, tetapi biasanya bekerja dalam satu menit bahkan untuk input serendah 50.sumber
r=''
sebagai "tak terbatas". Atau, lebih baik lagi, jangan menginisialisasir
dan gunakan diid
mana-manar
.Perl 6 , 29 byte
Terinspirasi oleh solusi Mathematica Martin Ender .
Membuat urutan bilangan bulat acak tak terbatas malas antara 0 dan 2 ^ 30-1, dan mengambil yang pertama yaitu antara 0 dan input.
Cobalah online!
sumber
05AB1E , 11 byte
Cobalah online!
Penjelasan
Karena daftar
[0 ... 2147483648]
terlalu besar untuk TIO, maka tautannya akan digunakan1.000.000
.Alternatif (rata-rata) solusi 11 byte yang jauh lebih cepat
Cobalah online
Penjelasan
sumber
žJL.R%
untuk 6 kecuali saya kehilangan sesuatu yang besar. Tekan 2 ^ 32, daftar dari 0 hingga 2 ^ 32, pilih acak. Input modulo. Benar-benar akan merusak efisiensi yang Anda miliki.I
di sana selama 7 byte untuk mendapatkan argumen untuk modulus dalam urutan yang benar (dan mungkinÝ
bukanL
), tetapi sebaliknya itu tentu saja solusi yang lebih pendek. Saya melihat Dennis melakukan itu dalam jawaban Jelly-nya, tetapi karena ini adalah ide pertama saya, saya menyimpan ini. Karena pendekatan itu berbeda dari ini, Anda dapat mempostingnya sebagai jawaban terpisah.DI‹Ï
akan menghindari loop.0
hampir selalu menghasilkan loop yang hampir tak terbatas, membuatnya sulit untuk diakhiri. Meskipun solusinya memungkinkan untuk mengakhiri dalam semua skenario itu tidak dijamin karena keacakan.Python 2, 89 byte
Penjelasan
Ini sangat tidak efisien, karena menciptakan 2 ^ 31 bilangan bulat, mengocok dan memfilternya.
Saya tidak melihat gunanya membagikan tautan TIO, di mana ia membuat daftar besar, jadi di sini ada tautan TIO untuk
n
= 100.Cobalah online!
sumber
Java 8,
8483807162 byte-1 byte terima kasih kepada @ OliverGrégoire .
-3 byte terima kasih kepada @Jakob .
-9 byte mengkonversi Java 7 ke Java 8.
-9 byte dengan mengubah
java.util.Random().nextInt(1<<30)
ke(int)(Math.random()*(1<<30))
.Penjelasan:
Coba di sini.
CATATAN: Mungkin jelas butuh waktu sangat lama untuk input kecil.
Contoh output:
sumber
2^30
=1073741824
. Anda lebih suka menggunakan-1>>>1
(=2147483647
). Tapi ini ada:1<<30
yang persis sama dengan2^30
; dan lebih pendek 1 byte.int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}
?Math.random()
bukanjava.util.Random().nextInt
.Python 3, 51 byte
Berikut ini adalah solusi python dengan sumber acak yang tidak lazim.
Cobalah online!
Jadi untuk memecah ini.
Mendapat nomor input, dan menambahkannya
1
.Membuat set
{0, 1, 2, 3, 4, ... n}
untuk semua hasil yang mungkin.Mengambil set, mengonversinya menjadi daftar, dan mengambil item pertama.
Ini berfungsi karena dalam Python 3, urutan
set()
didirikan oleh PYTHONHASHSEED ( tidak dapat diperoleh tetapi ditetapkan pada eksekusi skrip).Memang, saya menduga bahwa ini adalah distribusi yang seragam, karena
hash()
nilainya ditentukan secara acak dan saya melihat secara acak memilih nilainya dengan spesifikhash()
, alih-alih hanya mengembalikanhash(input())
sendiri.Jika ada yang tahu apakah ini distribusi yang seragam, atau bagaimana saya bisa mengujinya, silakan komentar.
sumber
C #, 57 byte
Fungsi anonim yang mengembalikan bilangan bulat antara 0 dan n inklusif.
Semakin kecil nomor input, semakin lama waktu untuk mengembalikan nilai acak.
Program lengkap:
sumber
Next
tidak statis.Bash + coreutils, 20 byte
Golf
seq 0 $ 1 | shuf | sed 1q
Shuf akan menggunakan kode berikut : untuk menghasilkan permutasi:
yang berakhir pada
randint_genmax
yang, pada gilirannya, akan membaca beberapa byte data acak dari sumber tingkat keacakan yang rendah:
yaitu pada level rendah, tidak ada ketergantungan langsung antara nilai
shuf
input dan data yang dibaca dari sumber keacakan (selain dari menghitung kapasitas buffer byte yang diperlukan).sumber
jot will arrange for all the values in the range to appear in the output with an equal probability
(itu mungkin garis batas, tetapi masih).SmileBASIC, 38 byte
Menghasilkan angka acak hingga mendapat nomor yang lebih kecil dari input.
sumber
Ruby,
23 15 23 3229 byteBagaimana itu bekerja:
1while [...];
menjalankan pernyataan setidaknya sekali:1
sebelumwhile
bertindak sebagai tidaksumber
Ohm, 26 byte
Penjelasan:
sumber
Pergi,
6361 byteGunakan seperti ini:
Mengujinya langsung di taman bermain go
sumber
Golang,
847871 bytePengambilan sampel penolakan sederhana.
Catatan: karena matematika / rand seed adalah konstanta 1, pemanggil harus seed kecuali hasil yang konstan diinginkan.
Uji: https://play.golang.org/p/FBB4LKXo1rPraktis tidak lagi dapat diuji pada sistem 64-bit, karena itu mengembalikan keacakan 64-bit dan menggunakan pengujian penolakan.sumber
import."math/rand"
makaInt31
tersedia di namespace global dan Anda dapat menghemat 4 byte, jugaint
dijamin setidaknya 32 bit, menghemat 6 byte lagi:=
sintaks untuk 3 byte lainnyaInt()
fungsi dalam paket rand, juga, Anda dapat menghapus ruang setelahimport