Sửa một hàm ngẫu nhiên bị hỏng


18

Một người bạn có một thẻ bổ trợ trong máy tính của họ, tạo ra một số hoàn toàn ngẫu nhiên từ 1 đến 5. Thật không may, họ đã làm đổ cola lên nó bằng cách nào đó và hiện tại nó chỉ tạo ra 2 giây cho tất cả các số từ 1 đến 4. May mắn là sự ngẫu nhiên được bảo toàn, nhưng 2 có xác suất 80% và 5 có xác suất 20%, và không có 1, 3 hoặc 4 được tạo. Sử dụng nguồn ngẫu nhiên này (gọi nó BrokenRand()hoặc một cái gì đó tương tự), viết một trình tạo số ngẫu nhiên hoạt động, tạo ra các số từ 1 đến 5 mỗi số với xác suất 20% bằng nhau với độ ngẫu nhiên hoàn hảo giống như nguồn ban đầu.

Chương trình ngắn nhất sẽ thắng. Điểm thưởng được trao cho số lượng cuộc gọi tối thiểu đến BrokenRandmột cách vô tư bởi một tư vấn tập trung vào dịch vụ khách hàng được lựa chọn theo nhân khẩu học, được chia theo độ tuổi và giới tính - tức là tôi.

Câu trả lời:


10

JavaScript - 69 ký tự

Điều này sử dụng trình trích xuất von Neumann để tạo ra các bit không thiên vị; thuật toán chung cũng được mô tả trên trang web HotBits . Ba bit được sử dụng để tạo thành một số từ 0 đến 7. Tất cả các số 5 trở lên được loại bỏ và 1 được thêm vào mỗi phần còn lại trước khi chúng được in. Tôi đã thực hiện một mô phỏng để chỉ ra rằng điều này không quá thiên vị .

Bạn cần cung cấp chức năng của riêng mình r()để truy cập RNG.

 for(;;v<5&&alert(v+1))for(v=i=0;i<3;a-b&&(v*=2,v+=a<b,i++))b=r(a=r())

Điều này thực sự được thực hiện tốt! Tôi thích cách bạn ngắn mạch giá trị tăng.
snmcdonald

Bạn có thể tạo 7 bit và trích xuất 3 số ngẫu nhiên để giảm các cuộc gọi đến BrokenRand, nhưng điều đó có thể sẽ tốn thêm một vài nét
gnibbler

5

scala 79 ký tự:

// preparation: 
val r = util.Random 
def defektRNG = if (r.nextInt (5) == 0) 5 else 2 

(1 to 20).foreach (_ => print (" " + defektRNG))
// first impression:
// 2 2 2 2 2 2 2 5 2 2 5 2 2 2 5 2 2 2 2 2

def rnd : Int = { val k = (1 to 5).map (_ => defektRNG)
  if (k.sum == 13) k.findIndexOf (_ == 5) + 1 else rnd } 

// first impression:
(1 to 20).foreach (_ => print (" " + rnd))             
// 3 3 2 3 5 2 2 5 1 1 3 4 3 2 5 3 3 1 5 4
// control:
(1 to 50000).map (_ => rnd).groupBy (identity) .map (_._2.length) 
// scala.collection.immutable.Iterable[Int] = List(10151, 9997, 9971, 9955, 9926)

Bây giờ đối với golf thực sự, bí danh defektRNG bị hỏngRand được đổi tên thành b.

def r:Int={val k=(1 to 5).map(_=>b)
if(k.sum==13)k.findIndexOf(_==5)+1 else r} 

Cách thức hoạt động: Thông thường, b trả về một chuỗi 2 giây. Nhưng nếu bạn thực hiện 5 cuộc gọi đến b, bạn sẽ rất thường kết thúc với kết quả là 4x2 và 1x5, đây là sự kiện có thể xảy ra thứ hai và có thể là 5-2-2-2-2, 2-5-2-2 -2, 2-2-5-2-2, 2-2-2-5-2 và 2-2-2-2-5.

Chúng có điểm chung, đó là tổng là 4 * 2 + 5 = 13. Chỉ số của năm đầu tiên có thể được sử dụng để xác định một số ngẫu nhiên hợp lệ. Nếu có nhiều hơn hoặc ít hơn một 5, tổng 13 hoặc thấp hơn 13, lặp lại.

Một bộ đếm trong 'rnd' aka 'r' có thể hiển thị trung bình có bao nhiêu cuộc gọi cần thiết để tạo ra các số. Có 121 200 cuộc gọi đến r cho 50 000 số ngẫu nhiên, điều này không gây ấn tượng. :)


3

> <> (Cá) - 55 byte

Đã cập nhật để sử dụng thuật toán tương tự như @user chưa biết trong câu trả lời scala của anh ấy

<v? = d + &: i & + &: i & + &: i & + &: i &: i
 0
 > 1 + $ 5 (? Vnao;
 ^ <

Nó hy vọng máy phát điện bị hỏng sẽ được kết nối với stdin; đây là kịch bản python tôi đã sử dụng . Mã phù hợp với thông số cá hiện tại, nhưng tôi đã sử dụng một phiên bản sửa đổi của trình thông dịch cũ.

bash:$ for i in $(seq 1000); do ./bad_rand.py | ./myfish.py rand.fish; done >res.txt
bash:$ for i in $(seq 5); do echo -n "$i : "; grep -c $i res.txt; done
1 : 193
2 : 204
3 : 198
4 : 206
5 : 199

Tôi sẽ làm một mẫu lớn hơn nhưng nó chậm.


2

GolfScript, 23 byte

Câu trả lời muộn, nhưng vì điều này chỉ tình cờ xuất hiện trên trang nhất ...

0{;[{r}5*].5?)\5-,4-}do

Sử dụng thuật toán tương tự như giải pháp Scala của người dùng chưa biết . Giả sử rằng trình tạo số ngẫu nhiên sai lệch được đưa ra dưới dạng chương trình con GolfScript có tên r; bạn có thể tự xác định một RNG thiên vị phù hợp, ví dụ như:

{5rand!3*2+}:r;

Đây là một thử nghiệm nhanh cho thấy sự thiếu thiên vị. Thật không may, máy chủ GolfScript trực tuyến khá chậm, vì vậy tôi đã phải cắt phần trình diễn xuống chỉ còn 100 mẫu để hoàn thành đúng hạn. Nếu chạy thử nghiệm tại địa phương với các thông dịch viên GolfScript , hãy thử tăng 100*tới 1000*hoặc thậm chí 10000*.

(Máy chủ GolfScript đôi khi cũng đóng băng ngẫu nhiên và hết thời gian. Nếu điều này xảy ra với bạn, hãy thử lại thường giải quyết nó. Nó cũng xảy ra với mã khác và chỉ xảy ra trên máy chủ chứ không phải trên máy tính của tôi, vì vậy tôi tự tin đó là sự cố với máy chủ chứ không phải mã của tôi.)


-1

javascript, 160 ký tự mà không làm giảm khả năng đọc hay tối ưu hóa

function giveRandom(){
    var result = Math.floor(5 * Math.random()) + 1;
    while(BrockenRand() != 5){
        result = Math.floor(5 * Math.random()) + 1;
    }
    return result;
}

@ snmcdonald -một số đó không phải là một lỗi đánh máy, đó là một cách để cải thiện js ngẫu nhiên bằng một trình tạo ngẫu nhiên hoàn hảo chỉ chấp thuận (hoàn toàn ngẫu nhiên!) 20% kết quả
www0z0k

Quan tâm để giải thích những gì BrockenBand(), sau đó?
Mateen Ulhaq

6
Tôi nghĩ rằng bạn đã bỏ lỡ điểm
cthom06

@muntoo - ý nghĩaBrockenRand
www0z0k

Lưu một vài byte theo cách này:function giveRandom(){return Math.ceil(Math.random()*5)}
user300375
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.