Xúc xắc từ thay đổi máy phát ngẫu nhiên


10

Giới thiệu

Bạn được cung cấp một trình tạo số nguyên ngẫu nhiên với cách thực hiện sau

  • Lời gọi đầu tiên luôn trả về 1.
  • Lệnh thứ hai trả về một số nguyên ngẫu nhiên trong khoảng từ 1 đến 2.
  • Lệnh thứ ba trả về một số nguyên ngẫu nhiên trong khoảng từ 1 đến 3.
  • Lệnh thứ n trả về một số nguyên ngẫu nhiên trong khoảng từ 1 đến n, đã bao gồm.

Dựa vào hàm trên, hãy viết một bộ tạo xúc xắc ngẫu nhiên hoàn toàn ngẫu nhiên, trả về giá trị từ 1 đến 6 (đã bao gồm) với xác suất bằng nhau.

Quy tắc

  • Chương trình / hàm của bạn sẽ dẫn đến một số nguyên ngẫu nhiên trong khoảng từ 1 đến 6, bao gồm, ở một số dạng có thể sử dụng, nghĩa là, cho đầu ra tiêu chuẩn hoặc dưới dạng giá trị trả về của hàm.
  • Trình tạo số ngẫu nhiên tăng dần ở trên có thể được định nghĩa là hàm "miễn phí" trong chương trình của bạn (nghĩa là không tính vào số ký tự của bạn) hoặc một tập lệnh / chương trình riêng được thực thi khi cần, giả sử trạng thái ( n) vẫn tồn tại giữa các cuộc gọi.
  • Giả sử rằng sẽ không yêu cầu quá 1000 cuộn xúc xắc trong một trường hợp sử dụng duy nhất của chương trình của bạn và trình tạo số ngẫu nhiên ban đầu có thể được đặt lại 1ở cuối 1000 cuộn xúc xắc để tránh tràn n.
  • Chương trình của bạn không được sử dụng bất kỳ nguồn số ngẫu nhiên nào khác ngoại trừ trình tạo ngẫu nhiên tăng dần được xác định ở trên. Tất nhiên bạn có thể yêu cầu nhiều số ngẫu nhiên từ trình tạo số ngẫu nhiên cho mỗi đầu ra cuộn xúc xắc duy nhất.
  • Đây là môn đánh gôn, vì vậy người chiến thắng là câu trả lời ngắn nhất hoặc hầu hết phiếu bầu trong trường hợp hòa. Nếu bạn có thể tạo 1000 cuộn xúc xắc bằng cách sử dụng ít hơn 1000 số ngẫu nhiên được tạo, hãy tạo cho mình phần thưởng hiệu quả 10 điểm .

Thí dụ

./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

Là chương trình iterate(6):b=asc-rand(); print bbất hợp pháp hoặc nó không hoạt động? Tôi có thể hiểu sai quy tắc thứ ba.
beary605

@ beary605: Trình tạo số ngẫu nhiên chỉ có thể được đặt lại sau toàn bộ 1000 cuộn xúc xắc, không phải giữa mỗi lần tung xúc xắc. Lý do duy nhất tôi đề cập đến là việc xử lý các lỗi tràn giá trị mà bộ tạo số ngẫu nhiên trả về không phải là một trong những mối quan tâm trong thử thách này. Chỉnh sửa: Tôi đã làm rõ mục đích của quy tắc, hy vọng nó sẽ giúp.
mellamokb

Khi bạn nói "số ngẫu nhiên", bạn có nghĩa là "số nguyên ngẫu nhiên" hay "số thực ngẫu nhiên (cắt ngắn)"? Có lẽ có một số quy ước mà tôi không nhận thức được.
DavidC

@DavidCarraher: Điểm rất tốt. Tôi có nghĩa là số nguyên ngẫu nhiên, và tôi thấy điều đó không rõ ràng. Tôi sẽ cập nhật câu hỏi. Chỉnh sửa: Cập nhật.
mellamokb

1
Chúng ta có được phép hỏi ngẫu nhiên số lần tạo số ngẫu nhiên không? Tôi đã có ấn tượng rằng chúng tôi không thể.
Matt

Câu trả lời:


2

J - 13 char

Điều này đưa ra các giả định tương tự như Golfscript: số lượng xúc xắc có trong stdin và chúng tôi liệt kê các cuộn súc sắc sẽ xuất hiện.

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

Giải thích bằng vụ nổ:

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

Nếu điều đó không thỏa đáng, thì đây là một chương trình dài hơn 21 ký tự, có thể được gọi f''để tạo các số ngẫu nhiên, có trạng thái và mọi thứ.

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

Tương tự K: chức năng ngẫu nhiên miễn phí r:{*1_draw x}, phiên bản stdin (10 char) r'1+!. 0:` , phiên bản chức năng (14 char) c:0;f:{r@c+:1}được gọi bởi f[].
thuật toán

6

Python, 31 ký tự

Tương tự như scleaver, định nghĩa trình tạo như thế này:

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

Sau đó, một chức năng để trả lại cuộn xúc xắc:

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

Gọi D()bất cứ lúc nào bạn cần một cuộn súc sắc ngẫu nhiên đồng đều.


Ah, sử dụng thông minh của eval, tôi thích nó.
scleaver

3

Scala 23

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

Phương thức r có thể (xấp xỉ) được triển khai như thế này:

var cnt = 0 
val rnd = new util.Random 

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

một bài kiểm tra thô:

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)

Mỗi cuộc gọi thứ 6 sẽ tạo ra một phân phối bằng nhau trên 6 giá trị, vì vậy tôi vứt đi 5.


2

GolfScript (15 ký tự)

Điều này giả định rằng số lượng cuộn yêu cầu được cung cấp trên stdin và liệt kê nhiều kết quả cho thiết bị xuất chuẩn.

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

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

Bản demo trực tuyến

Mặc dù tôi có thể nhận được phần thưởng 10 điểm khi sử dụng ít hơn 1000 cuộn để tạo 1000 số, nhưng nó sẽ tiêu tốn của tôi hơn 10 ký tự. Cách tiếp cận tầm thường của việc trích xuất entropy phù hợp khi N là bội số của công suất 2 hoặc 3 giảm rất ngắn vì số lượng kết quả có sẵn mod 3 chỉ là 333 + 111 + 37 + 12 + 4 + 1 = 498. Do đó, cần phải có một cách tiếp cận mẫu và từ chối. Sử dụng phương pháp này, bạn có thể nhận được 2242 cuộn dự kiến ​​từ 1000 cuộc gọi đến r, nhưng có thêm chi phí từ việc giữ sổ sách và baselà một tên chức năng rất dài.


5
"Và baselà một tên hàm rất dài" Bạn dường như không sử dụng Mathicala . Chúng tôi nhận được điều kỳ diệu như NegativeBinomialDistribution, ExponentialGeneratingFunction, MathieuCharacteristicExponent, InverseFourierSequenceTransform, và SemialgebraicComponentInstances. :-)
Mr.Wizard

1

Con trăn 65 63

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

Các chức năng R()là ngẫu nhiên tăng dần.

Sử dụng:

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

Tại sao không thoát khỏi forvòng lặp của bạn và chỉ gọi Rmột lần trước whilevòng lặp của bạn ?
Keith Randall

@KeithRandall Số tôi trả về khi cuộn xúc xắc của tôi là chữ số cuối cùng của số mà trình tạo tăng dần trả về. Tôi cần thực hiện 10 cuộc gọi đến trình tạo tăng dần để đảm bảo xác suất bằng nhau cho tất cả các chữ số có thể.
Matt

Tại sao 10 cuộc gọi? Về nguyên tắc, nếu trình tạo ngẫu nhiên, mỗi cuộc gọi có nên cung cấp xác suất bằng nhau cho bất kỳ (mười) chữ số nào không? Tất nhiên, trong thực tế, bạn chỉ có thể mong đợi tiếp cận số lượng bằng nhau cho mỗi số.
DavidC

@DavidCarraher Trình tạo trả về các số ngẫu nhiên từ 1 đến n trong đó n là số lần bạn đã gọi nó. Tôi đang nhìn vào chữ số cuối cùng của số trả về này. Nếu n không phải là bội số nguyên của 10 thì xác suất sẽ không đồng nhất. Ví dụ: Nếu n = 13, xác suất sẽ bị hỏng như sau: 1/9 cho các cuộn 1,5,6 và 2/9 cho các cuộn 2,3,4
Matt

@Matt: Tôi giả sử R()đã trả lại một số float và bạn đang lấy chữ số có nghĩa ít nhất. Bây giờ nó đã được làm rõ rằng R()trả về một số nguyên, nó có ý nghĩa.
Keith Randall

1

Con trăn, 56

r được định nghĩa là:

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

máy tạo xúc xắc d:

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

sử dụng, ví dụ, cho 100 cuộn:

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

bạn có thể xóa import mathnếu bạn thay thế math.ceil(...)bằngint(...)+1
Matt

Tôi sẽ, nhưng nó sẽ tạo ra 7 như một đầu ra có thể.
scleaver

Ồ, vâng. Tôi bỏ lỡ điều đó.
Matt

mellamokb đã làm rõ một câu hỏi tôi có về ngẫu nhiên tăng dần. Bạn không được phép hỏi nó cho n.
Matt

1

Toán học 51

Trình tạo số ngẫu nhiên r, được đặt lại bằng cách đặt biến toàn cục, nthành 1.

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

Không chạy trong mã ngắn nhất ...

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

Sử dụng

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

60000 cuộn xúc xắc yêu cầu 60031 cuộc gọi đến h. Tallyhiển thị bảng phân tích theo các số 1-6.

60031

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


1

Perl, 22 hoặc 45

Thực hiện trình tạo số ngẫu nhiên tăng dần:

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

Tạo:

#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 }

Kiểm tra ra:

n số chisapes
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 cuộn xúc xắc mất 60000042 cuộc gọi đến r và 570.432735 giây


0

op86 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

Rõ ràng đây là một bài chất lượng thấp?
Muhammad Salman

0

GolfScript , 8 byte

f;3f*f(-

Hãy thử trực tuyến!

Nó bật máy phát điện một lần, sau đó thoát khỏi kết quả. Sau đó, nó cuộn f2 và nhân nó với 3 (3 hoặc 6), sau đó trừ f3-1 (0, 1, 2) dẫn đến (3-2, 3-1, 3-0) hoặc (6-2, 6-1, 6-0) W5.

Golfscript và chức năng ngẫu nhiên tồn tại trước khi câu hỏi này được đăng, vì vậy là một đệ trình hợp pháp.

Đây là lần gửi chỉ chạy một lần. Nếu bạn cần chạy nó nhiều lần trong một cuộc gọi,

GolfScript , 12 byte

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

Hãy thử trực tuyến!

Điều này đặt lại tôi gọi đến 0 để nó đặt lại tương ứng. TIO này hiển thị 50 kết quả ngẫu nhiên.


0

C (gcc) , 31 byte

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

Cứ sau 6 cuộc gọi, xác suất của mọi số trong khoảng từ 1 đến 6 được bao gồm sẽ được tạo ra là bằng nhau.

c#defined như một cuộc gọi đến một hàm tạo ra các số ngẫu nhiên hoàn hảo.

Hãy thử trực tuyến!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.