Dadu dari Mengubah Generator Acak


10

pengantar

Anda diberi generator integer acak dengan implementasi berikut

  • Doa pertama selalu mengembalikan 1.
  • Doa kedua mengembalikan integer acak antara 1 dan 2.
  • Doa ketiga mengembalikan integer acak antara 1 dan 3.
  • Doa n mengembalikan integer acak antara 1 dan n, inklusif.

Berdasarkan fungsi di atas, tulis generator dadu acak yang sangat acak, mengembalikan nilai antara 1 dan 6 (inklusif) dengan probabilitas yang sama.

Aturan

  • Program / fungsi Anda harus menghasilkan bilangan bulat acak antara 1 dan 6, inklusif, dalam beberapa bentuk yang dapat digunakan, yaitu, untuk output standar atau sebagai nilai pengembalian fungsi.
  • Generator angka acak yang naik di atas dapat didefinisikan sebagai fungsi "bebas" dalam program Anda (yaitu, tidak dihitung terhadap jumlah karakter Anda), atau skrip / program terpisah yang dijalankan sesuai kebutuhan, dengan asumsi state ( n) persisten antar panggilan.
  • Asumsikan bahwa tidak lebih dari 1000 gulungan dadu akan diminta dalam satu kasus penggunaan program Anda, dan generator nomor acak awal dapat diatur ulang 1pada akhir 1000 gulungan dadu untuk menghindari kelebihan n.
  • Program Anda mungkin tidak menggunakan salah sumber lain dari angka acak kecuali acak naik didefinisikan di atas. Anda tentu saja dapat meminta beberapa nomor acak dari generator nomor acak untuk setiap output gulungan dadu tunggal.
  • Ini adalah kode-golf, jadi pemenang adalah jawaban terpendek atau suara terbanyak dalam hal seri. Jika Anda dapat menghasilkan 1.000 dadu gulungan menggunakan kurang dari 1000 angka acak yang dihasilkan, beri diri Anda bonus efisiensi 10 poin .

Contoh

./asc-rand
1 # random integer between 1 and 1
./asc-rand
1 # random integer between 1 and 2
./asc-rand
3 # random integer between 1 and 3
./asc-rand
4 # random integer between 1 and 4

# dice-gen generates random dice based on output of asc-rand program.
./dice-gen
3
./dice-gen
6
./dice-gen
5
./dice-gen
1

Apakah program itu iterate(6):b=asc-rand(); print bilegal atau tidak berfungsi? Saya mungkin salah mengerti aturan ketiga.
beary605

@ beary605: Generator angka acak hanya dapat diatur ulang setelah seluruh 1000 gulungan dadu, bukan di antara setiap gulungan dadu. Satu-satunya alasan saya menyebutkan bahwa begitu berurusan dengan kemungkinan meluap pada nilai yang dikembalikan oleh generator angka acak bukan salah satu masalah dalam tantangan ini. Sunting: Saya menjelaskan tujuan aturan ini, semoga membantu.
mellamokb

Ketika Anda mengatakan "angka acak", maksud Anda "bilangan bulat acak" atau "bilangan real acak (terpotong)"? Mungkin ada beberapa konvensi yang tidak saya sadari.
DavidC

@ Davidvidarraher: Poin yang sangat bagus. Saya berarti bilangan bulat acak, dan saya melihat itu tidak jelas. Saya akan memperbarui pertanyaan. Edit: Diperbarui.
mellamokb

1
Apakah kita boleh bertanya kepada pengacak berapa kali telah menghasilkan angka acak? Saya mendapat kesan bahwa kita tidak bisa.
Matt

Jawaban:


2

J - 13 char

Ini membuat asumsi yang sama dengan Golfscript: bahwa jumlah dadu ada di stdin dan kami daftar gulungan dadu yang akan keluar.

r=:1+?  NB. free random function
r>:i.".1!:1]1

Dijelaskan oleh ledakan:

r=:1+?           NB. r(x) = 1 + a random number between 0 and n-1
           ]1    NB. input file handle
       1!:1      NB. read in a string
     ".          NB. convert to integer
 >:i.            NB. make a list of numbers, from 1 to that integer
r                NB. apply the random function

Jika itu entah bagaimana tidak memuaskan, ini adalah program 21-char yang lebih panjang, yang dapat dipanggil dengan f''untuk menghasilkan angka acak, menampilkan keadaan dan segalanya.

r=:1+?  NB. free random function
c=:0
f=:3 :'r c=:1+c'

K analog: fungsi acak gratis r:{*1_draw x}, versi stdin (10 char) r'1+!. 0:` , versi fungsi (14 char) c:0;f:{r@c+:1}dipanggil oleh f[].
algorithmshark

6

Python, 31 karakter

Demikian pula untuk scleaver, tentukan generator seperti ini:

from random import randint
n=0
def r():
    global n;n+=1
    return randint(1,n)

Kemudian fungsi untuk mengembalikan gulungan dadu:

D=lambda:eval('r(),'*6)[-1]%6+1

Panggil D()kapan saja Anda membutuhkan gulungan dadu acak yang seragam.


Ah, penggunaan pintar eval, aku suka itu.
scleaver

3

Scala 23

def s={r;r;r;r;r;r%6+1}

Metode r dapat (kurang-lebih) diimplementasikan seperti ini:

var cnt = 0 
val rnd = new util.Random 

def r = {
  cnt %= 1000
  cnt += 1
  rnd.nextInt (cnt)
}

tes kasar:

scala> (1 to 6).map (i => ((1 to 600) map (_=>s)).filter (_ == i).size)
res26: scala.collection.immutable.IndexedSeq[Int] = Vector(110, 105, 91, 96, 106, 102)

Setiap panggilan ke-6 harus menghasilkan distribusi yang sama di atas nilai-nilai 6, jadi saya membuang 5.


2

GolfScript (15 karakter)

Ini mengasumsikan bahwa jumlah gulungan yang diperlukan disediakan pada stdin dan daftar yang banyak hasilnya harus stdout.

# The free increasing random function
0:N;{N):N rand)}:r;

~{r{;r}5*6%)n}*

Demo online

Sementara saya bisa mendapatkan bonus 10 poin karena menggunakan kurang dari 1000 gulungan untuk menghasilkan 1000 angka, saya akan dikenakan biaya lebih dari 10 karakter. Pendekatan sepele dari mengekstraksi entropi yang sesuai ketika N adalah kelipatan dari kekuatan 2 atau 3 gagal karena jumlah hasil yang tersedia mod 3 hanya 333 + 111 + 37 + 12 + 4 + 1 = 498. Oleh karena itu perlu untuk mengambil pendekatan sampel-dan-tolak. Dengan menggunakan pendekatan ini Anda bisa mendapatkan 2242 gulungan yang diharapkan dari 1.000 panggilan r, tetapi ada biaya tambahan dari pembukuan dan basemerupakan nama fungsi yang sangat panjang.


5
"dan basenama fungsi yang sangat panjang" Anda tampaknya tidak menggunakan Mathematica . Kami mendapatkan keajaiban seperti NegativeBinomialDistribution, ExponentialGeneratingFunction, MathieuCharacteristicExponent, InverseFourierSequenceTransform, dan SemialgebraicComponentInstances. :-)
Mr.Wizard

1

Python 65 63

i=7
while i>5:[R()for x in range(9)];i=int(`R()`[-1])
print i+1

Fungsinya R()adalah randomizer ascending.

Pemakaian:

$ ./rollDice.py
3
$ ./rollDice.py
5

Mengapa tidak singkirkan forloop Anda dan panggil Rsekali saja sebelum whileloop Anda ?
Keith Randall

@ KeithRandall Nomor yang saya kembalikan sebagai gulungan dadu saya adalah digit terakhir dari nomor yang dikembalikan oleh generator yang naik. Saya perlu melakukan 10 panggilan ke generator naik untuk memastikan probabilitas yang sama untuk semua digit yang mungkin.
Mat

Mengapa 10 panggilan? Pada prinsipnya, jika generator acak, bukankah masing-masing panggilan menawarkan probabilitas yang sama untuk satu (sepuluh) digit? Tentu saja, dalam praktiknya, Anda hanya bisa berharap untuk mendekati jumlah yang sama untuk masing-masing angka.
DavidC

@ DavidCarraher Generator mengembalikan angka acak dari 1 ke n di mana n adalah berapa kali Anda menyebutnya. Saya melihat angka terakhir dari angka yang dikembalikan ini. Jika n bukan kelipatan bilangan bulat dari 10 probabilitas tidak akan seragam. Sebagai contoh: Jika n = 13 probabilitas akan terurai sebagai berikut: 1/9 untuk gulungan 1,5,6 dan 2/9 untuk gulungan 2,3,4
Matt

@ Mat: Saya berasumsi R()sedang mengembalikan float dan Anda meraih angka paling tidak signifikan. Sekarang telah diklarifikasi yang R()mengembalikan integer, masuk akal.
Keith Randall

1

Python, 56

r didefinisikan sebagai:

from random import randint
n=0
def r(z):
    global n;n+=1
    return randint(1,n)

generator dadu:

import math;d=lambda:math.ceil(6.*r(r(r(r(r(r(0))))))/n)

penggunaan, misalnya, untuk 100 gulungan:

for i in range(100):print d()

Anda mungkin dapat menghapus import mathjika Anda ganti math.ceil(...)denganint(...)+1
Matt

Saya akan, tetapi akan menghasilkan 7 sebagai output yang mungkin.
scleaver

Oh ya. Saya melewatkan itu.
Matt

mellamokb mengklarifikasi pertanyaan yang saya miliki tentang pengacak naik. Anda tidak diizinkan untuk meminta n.
Mat

1

Mathematica 51

Generator angka acak r,, diatur ulang dengan mengatur variabel global, nke 1.

n = 1; r[c_] := RandomInteger[{1, c}]

Kode

Tidak dalam menjalankan kode terpendek ...

h := (n++; If[n < 4 \[Or] (y = r@n) > 6 Quotient[n, 6], h, y~Mod~6 + 1])

Pemakaian

t = Table[h, {60000}];
n
SortBy[Tally[t], First]

60000 gulungan dadu diperlukan 60031 panggilan ke h. Tallymenunjukkan rincian dengan angka 1-6.

60031

{{1, 9923}, {2, 9966}, {3, 10016}, {4, 10028}, {5, 10009}, {6, 10058}}


1

Perl, 22 atau 45

Implementasi generator nomor acak yang naik:

my $n=0;
sub r { $n++; return 1+int(rand$n); }

Menghasilkan:

#copy of the Scala solution; short code; uses 6N rolls
sub s{r;r;r;r;r;1+r%6}
#more efficient implementation, uses approximately 6+N+lnN rolls
sub roll { do{$a=r-1}while($a>$n-$n%6);return 1+(1+$a)%6 }

Menguji:

n nomor chisquare
1 10001867 0.348569
2 10004853 2.355161
3 9994395 3.141602
4 10000177 0,003133
5 9999227 0,059753
6 9999481 0,026936
T 60000000 5.935154
60000000 roll dadu mengambil 60000042 panggilan ke r dan 570.432735 detik


0

opcode x86, 15 byte

f:  mov cx, 6
    call r ; return in AX
    loop $-3
    cwd
    div word [f+1]
    inc dx
    ret ; return in DX

Ternyata ini adalah posting berkualitas rendah?
Muhammad Salman

0

GolfScript , 8 byte

f;3f*f(-

Cobalah online!

Ini muncul generator sekali, kemudian singkirkan hasilnya. Kemudian ia menggulung f2, dan mengalikannya dengan 3 (3 atau 6), lalu kurangi f3-1 (0, 1, 2) yang menghasilkan (3-2, 3-1, 3-0) atau (6-2, 6-1, 6-0) W5.

Golfscript dan fungsi acak ada sebelum pertanyaan ini diposting, begitu juga pengiriman yang sah.

Ini adalah pengajuan run-only-once. Jika Anda perlu menjalankannya beberapa kali dalam satu panggilan,

GolfScript , 12 byte

f;3f*f-)0:i;

Cobalah online!

Ini me-reset panggilan saya ke 0 sehingga me-reset sesuai. TIO ini menunjukkan 50 hasil acak.


0

C (gcc) , 31 byte

f(i){for(i=5;i--;)c;i=~-c%6+1;}

Setiap 6 panggilan, probabilitas setiap angka antara 1 dan 6 inklusif yang dihasilkan adalah sama.

cadalah #defined sebagai panggilan ke fungsi yang menghasilkan angka acak sempurna.

Cobalah online!

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.