Mô phỏng vấn đề Monty Hall [đóng]


8

Tôi chưa bao giờ có thể quấn đầu xung quanh vấn đề Monty Hall . Đây là tiền đề:

Giả sử bạn đang tham gia một chương trình trò chơi và bạn được lựa chọn ba cửa: Đằng sau một cánh cửa là một chiếc ô tô; Đằng sau những người khác, dê. Bạn chọn một cánh cửa, nói số 1, và chủ nhà, người biết những gì đằng sau cánh cửa, mở ra một cánh cửa khác, nói số 3, có một con dê. Sau đó, anh ta nói với bạn, "Bạn có muốn chọn cửa số 2 không?" Đó là lợi thế của bạn để chuyển đổi sự lựa chọn của bạn?

Chạy 10.000 mô phỏng. Xuất ra tỷ lệ phần trăm thắng của chuyển đổi. Ví dụ:

> 66.66733%

5
Chủ nhà biết chiếc xe đang ở đâu, vì vậy anh ta không bao giờ mở cửa với chiếc xe phía sau
uốn cong

6
Khi thách thức diễn ra, thật khó để tranh luận rằng nó không hoàn toàn hợp pháp khi chỉ có 10.000 lần chạy trình tạo số ngẫu nhiên và cộng lại những cái nào hạ cánh xuống dưới 0,6666. Bạn có thể nói rằng nó không thực sự mô phỏng vấn đề Monty Hall. Nhưng nếu nó tạo ra cùng một đầu ra, vậy thì cái gì thực sự thiếu?
hộp bánh mì

Một viễn cảnh lịch sử thú vị (về vấn đề chứ không phải chơi gôn): Cadillac có cánh cửa nào? .
Cary Swoveland

3
Thách thức vẫn còn một chút mơ hồ liên quan đến những giả định mà chúng tôi được phép đưa ra. Ví dụ, một số câu trả lời có thể đang tiết kiệm một lượng mã đáng kể bằng cách giả sử chiếc xe sẽ ở đằng sau cùng một cửa mỗi lần hoặc người chơi chọn cùng một cửa mỗi lần.
Iszi

1
Việc liệt kê tất cả các khả năng ít nhất là chiếu sáng như tạo ra chúng một cách ngẫu nhiên ...
Daniel Cristofani

Câu trả lời:


4

JavaScript 52

for(i=s=0;i++<1e4;)s+=Math.random()<2/3;alert(s/100)

Cửa là 1: [0,1 / 3), 2: [1 / 3,2 / 3), 3: [2/3, 1)

Giả sử giải thưởng luôn ở cửa 3. Nếu khách chọn cửa 1 hoặc 2, trong phạm vi [0,2 / 3) và họ chuyển đổi, họ đã giành được giải thưởng.


1
Có vẻ như CoffeeScript cho phép chúng ta cạo sạch một ký tự:i=s=0;s+=Math.random()<2/3while i++<1e4;alert s/100
Kerrick

3

J: 17 15

100%~+/2>?1e4$3

Nó chọn một cửa ngẫu nhiên, hãy dán nhãn 0, 1 hoặc 2 trong đó 2 là cửa với xe hơi và tính toán lợi ích của việc chuyển đổi dựa trên logic này:

  • Nếu người chơi chọn cửa 0, chủ nhà sẽ mở cửa 1. Chuyển đổi sẽ kiếm cho người chơi một chiếc xe mới ( 1).
  • Nếu người chơi chọn cửa 1, chủ nhà sẽ mở cửa 0. Chuyển đổi sẽ kiếm cho người chơi một chiếc xe mới ( 1).
  • Nếu người chơi chọn cửa 2, cửa thắng, chủ nhà sẽ mở cửa 0 hoặc cửa 1. Dù bằng cách nào, nếu người chơi chuyển đổi, người đó sẽ tìm thấy một con dê ( 0).

Sau đó, nó tính kết quả là tổng của mảng trước đó, chia cho 100.

Tôi khá run với J nên tôi chắc chắn điều này có thể được cải thiện hơn nữa.


3

R 115 100

Các giả mô phỏng câu trả lời là 23 ký tự dài:

sum(runif(1e4)>1/3)/100

nhưng đây là một mô phỏng thực tế:

D=1:3
S=function(x)x[sample(length(x),1)]
sum(replicate(1e4,{
C=S(D)
P=S(D)
H=S(D[-c(C,P)])
F=D[-c(P,H)]
C==F
}))/100
  1. D là những cánh cửa có thể
  2. S là một hàm để chọn ngẫu nhiên một mục từ một vectơ
  3. Clà cánh cửa với chiếc xe (ngẫu nhiên trong số D)
  4. Plà cánh cửa được người chơi chọn (ngẫu nhiên trong số D)
  5. Hlà cửa được chọn bởi chủ nhà (ngẫu nhiên trong số Dtrừ CP)
  6. Flà cánh cửa cuối cùng được người chơi chọn (xác định: Dtrừ PH)
  7. thành công được đo bằng C==F.

trả về: [1] 66.731

Biên tập

Tôi có thể lưu một vài ký tự bằng cách không gán cho các biến và giả sử mà không mất tính tổng quát rằng C==1:

D=1:3;S=function(x)x[sample(length(x),1)];sum(replicate(1e4,{P=S(D);1==D[-c(P,S(D[-c(1,P)]))]}))/100

2

Perl, 98 89 83 75 72 71 ký tự

Đây là một câu trả lời nghiêm túc thực sự chạy mô phỏng:

sub c{($==rand 2)-"@_"?$=:&c}$n+=$%==c c($%=rand 3)for 1..1e4;say$n/100

Trong mỗi lần lặp lại, lựa chọn ban đầu của người chơi luôn là cửa số 2. Đầu tiên, cánh cửa với chiếc xe được cất giữ $%, sau đó một cánh cửa khác được chọn cho Monty Hall để lộ. Nếu cánh cửa còn lại bằng $%, vòng thắng.

(Biến punculation Perl $%$=được sử dụng vì chúng cắt ngắn số nguyên miễn phí.)


2

Quyền hạn - 168 131 125 115

Mã đánh gôn:

nal g Random;1..1e4|%{$C=g 3;$P=g 3;$T+=$C-eq(0..2|?{$_-ne$P-and$_-ne(0..2|?{$_-ne$P-and$_-ne$C}|g)})};"$($T/100)%"

Thay đổi từ bản gốc:
Cắt bớt 53 ký tự khỏi tập lệnh gốc với một số sửa đổi.

  • Đã xóa các khoảng trắng và dấu ngoặc đơn nơi PowerShell đang tha thứ cho nó.
  • Đã sử dụng một ForEach-Objectvòng lặp, thông qua %bí danh, thay vì while.
  • Phạm vi số được sử dụng (ví dụ 0..2:) thay vì các mảng được xác định rõ ràng.
  • Đã xóa writekhỏi lệnh cuối cùng - hóa ra tôi không cần nó sau tất cả.
  • Lật biểu thức cho lựa chọn của máy chủ xung quanh để sử dụng cú pháp đường ống ngắn hơn.
  • Thay thế 10000 bằng 1e4.
  • Mất gợi ý của Joey và bỏ qua Get-từ Get-Random. (Lưu ý: Việc sửa đổi này làm tăng đáng kể thời gian chạy. Trên hệ thống của tôi, nó đã tăng từ khoảng 20 giây lên gần nửa giờ mỗi lần chạy!)
  • Sử dụng thủ thuật của Rynant để làm $T+=...thay vì if(...){$T++}.

Một số lưu ý:

Kịch bản này được dự định là ngắn gọn nhất có thể, đồng thời cũng là một mô phỏng của kịch bản Monty Hall càng kỹ càng tốt. Nó không đưa ra giả định về việc chiếc xe sẽ ở đâu, hoặc người chơi sẽ chọn cửa nào trước. Giả định thậm chí không được thực hiện cho cửa cụ thể mà chủ nhà sẽ chọn trong bất kỳ kịch bản cụ thể nào. Các giả định duy nhất còn lại là những giả thuyết thực sự được nêu trong vấn đề Monty Hall:

  • Chủ nhà sẽ chọn một cửa mà người chơi không chọn trước, không chứa xe.
    • Nếu người chơi chọn cửa trước bằng ô tô, điều đó có nghĩa là có hai lựa chọn khả dĩ cho chủ nhà.
  • Lựa chọn cuối cùng của người chơi sẽ không phải là lựa chọn ban đầu của anh ta cũng không phải là lựa chọn của chủ nhà.

Ungolfed, với ý kiến:

# Setup a single-character alias for Random, to save characters later.
# Note: Script will run a lot (about 500 times) faster if you use Get-Random here.
# Seriously, as it currently is, this script will take about a half-hour or more to run.
# With Get-Random, it'll take less than a minute.
nal g Random;

# Run a Monty Hall simulation for each number from 1 to 10,000 (1e4).
1..1e4|%{

    # Set car location ($C) and player's first pick ($P) to random picks from a pool of 3.
    # Used in this way, Random chooses from 0..2.
    $C=g 3;$P=g 3;

    # Increment win total ($T) if the car is behind the door the player finally chooses.
    # (Player's final choice represented by nested script.)
    $T+=$C-eq(

        # Filter the doors (0..2) to determine player's final choice.
        0..2|?{

            # Player's final choice will be neither their original choice, nor the host's pick.
            # (Host's pick represented by nested script.)
            $_-ne$P-and$_-ne(

                # Filter the doors to determine host's pick.
                0..2|?{

                    # Host picks from door(s) which do not contain the car and were not originally picked by the player.
                    $_-ne$P-and$_-ne$C

                # Send filtered doors to Random for host's pick.
                }|g
            )
        }
    )
};

# After all simulations are complete, output overall win percentage.
"$($T/100)%"

# Variable & alias cleanup. Not included in golfed script.
rv C,P,T;ri alias:g

Tôi đã chạy tập lệnh này nhiều lần và nó luôn cho kết quả rất gần với xác suất hai phần ba. Một số mẫu:

(Như trên)

  • 67,02%

(Sử dụng Get-Randomnhư định nghĩa bí danh, thay vì chỉ Random)

  • 66,92%
  • 67,71%
  • 66,6%
  • 66,88%
  • 66,68%
  • 66,16%
  • 66,96%
  • 66,7%
  • 65,96%
  • 66,87%

2

Ruby 48 40 38

Mã của tôi không đưa ra bất kỳ giả định nào về việc cửa nào giải thưởng sẽ luôn ở phía sau hoặc cửa nào mà người chơi sẽ luôn mở. Thay vào đó, tôi tập trung vào những gì khiến người chơi thua cuộc. Theo bài viết trên Wikipedia :

[...] 2/3 thời gian, lựa chọn ban đầu của người chơi là một cánh cửa giấu một con dê. Khi đó là trường hợp, chủ nhà buộc phải mở cánh cửa dê khác [...] "Chuyển đổi" chỉ không cho xe khi người chơi chọn cửa "bên phải" (cửa ẩn xe) để bắt đầu.

Vì vậy, để mô phỏng điều này (thay vì sử dụng các giá trị cố định), tôi đã mô hình hóa nó như sau:

  • chương trình chọn ngẫu nhiên 1 trong 3 cửa để ẩn giải thưởng phía sau
  • Sau đó, người chơi chọn ngẫu nhiên 1 trong 3 cửa là lựa chọn đầu tiên của mình
  • Người chơi luôn chuyển đổi, vì vậy nếu lựa chọn đầu tiên của anh ta giống với lựa chọn của chương trình, anh ta sẽ thua

Mã v1:

w=0;10000.times{w+=rand(3)==rand(3)?0:1};p w/1e2

Mã v3 (cảm ơn steenslag và Iszi!):

p (1..1e4).count{rand(3)!=rand(3)}/1e2

Một số giá trị trả về mẫu:

  • 66,44
  • 66,98
  • 66,33
  • 67,2
  • 65,7

1
p (1..10000).count{rand(3)!=rand(3)}/1e2tiết kiệm một số ký tự.
steenslag

@steenslag À, quả thật là có! Cảm ơn bạn! =)
Jonathan Hefner

1
Có phải Ruby không cho phép cắt ngắn 10? Vd: 1e4cho 10000?
Iszi

@Iszi Nó có, nhưng ký hiệu khoa học mang lại sự nổi, vì vậy nó không thể luôn luôn được thay thế. Tuy nhiên, nó là một sự thay thế khả thi trong v2, tiết kiệm thêm 2 ký tự!
Jonathan Hefner

1

Toán học 42

Count[RandomReal[1,10^4],x_/;x>1/3]/100// N

66,79


1

PowerShell, 90

$i=0
1..10000|%{$g=random 3;$n=0..2-ne$g;$g=($n,2)[!!($n-eq2)]|random;$i+=$g-eq2}
$i/10000

Đã bình luận:

# Winning door is always #2

$i=0

# Run simulation 1,000 times
1..10000|%{

# Guess a random door
$g=random 3

# Get the doors Not guessed
$n=0..2-ne$g

# Of the doors not guessed, if either is the
# winning door, switch to that door.
# Else, switch to a random door.
$g=($n,2)[!!($n-eq2)]|random

# Increment $i if 
$i+=$g-eq2}

# Result
$i/10000

Điều này không tạo ra tỷ lệ phần trăm chiến thắng ở định dạng được chỉ định trong câu hỏi. Ngoài ra, lưu một vài ký tự bằng cách sử dụng 1e4thay vì 10000.
Iszi

1

C, 101 95

float c,s,t,i;main(){for(;i<1e5;i++,c=rand()%3,s=rand()%3)i>5e4&c!=s?t++:t;printf("%f",t/5e4);}

Đó là cho mô phỏng thực tế. Đối với một số mã bẻ cong quy tắc gian lận, nó chỉ có 71 65 59:

p,i;main(){for(;i<1e5;rand()%5>1?i++:p++)printf("%f",p/1e5);}

Tôi đã không làm srand () vì các quy tắc không nói rằng tôi phải làm. Ngoài ra, phiên bản gian lận in ra khoảng 30.000 số phụ vì nó lưu một ký tự. Tôi có thể thiếu một vài thủ thuật, nhưng tôi đã làm tốt nhất có thể.


Biến toàn cầu được đảm bảo bằng không khi khởi động. Di chuyển các khai báo biến của bạn ra mainvà bạn có thể bỏ các =0khởi tạo.
hộp bánh mì

1

Con trăn 2: 72 66 64

from random import*
i=10000
exec"i-=randint(0,2)&1;"*i
print.01*i

Ví dụ đầu ra: 66,49


1
Bạn có thể lưu một vài ký tự bằng cách sử dụng exec"i-=randint(0,2)&1;"*ithay vì forvòng lặp.
Phục hồi Monica

@WolframH Cảm ơn, tôi sẽ cập nhật ngay.
Rees

Ngoài ra, sử dụng print.01*ithay vì print i/100..
Phục hồi Monica

Giải pháp hay nhưng bạn đang thiếu một dấu chấm phẩy.
Daniel Lubarov

Rất đúng. Đang cập nhật ngay bây giờ ...
Rees

0

- 46 43

Điều này đang sử dụng các giả định tương tự mà Tristin đã đưa ra:

aa*v>1-:?v$aa*,n;
v*a<$v+1$x! <
>a*0^<  $<

Hướng xuống trên xđại diện cho bạn ban đầu chọn cửa chính xác, trái và phải là những trường hợp bạn chọn một cửa khác, và lên không có gì, và sẽ quay lại.

Ban đầu, tôi đã khởi tạo 10000với "dd"*, nhưng "dd"tất cả phải nằm trên cùng một dòng và tôi đã lãng phí một số khoảng trắng. Bằng cách bắt rắn, aa*a*a*tôi có thể xóa một cột và cuối cùng là 3 ký tự. Có một chút khoảng trắng còn lại mà tôi không thể thoát khỏi, tôi nghĩ rằng điều này là khá tốt!


0

PHP 140

Nhưng tôi nghĩ rằng điều này là không hoạt động đúng. Có mẹo gì không? Tôi đang nhận được các giá trị từ 49 đến 50.

$v=0;//victorys
for($i=0;$i<1e4;$i++){    
    //while the selection of the host ($r) equals the player selection or the car
    //h=removed by host, p=player, c=car
    while(in_array($h=rand(1,3),[$p=rand(1,3),$c=rand(1,3)])){}
    ($p!=$c)?$v+=1:0; //if the player changes the selection    
}
echo ($v/1e4)*100;

"Nếu người chơi thay đổi lựa chọn"?
TimTech

Xin lỗi tiếng anh của tôi không tốt Ý tôi là, đầu tiên tôi làm trong khi cố gắng để có được các giá trị có thể chấp nhận được. Bởi vì "chủ nhà" không thể loại bỏ một cánh cửa có chứa chiếc xe HOẶC cánh cửa mà bạn chọn. Sau đó, tôi có $ p (sự lựa chọn của người chơi) và $ c (nơi có xe). OP nói rằng bạn phải lấy tỷ lệ phần trăm chiến thắng khi bạn chuyển đổi, vì vậy tôi chỉ tính kết quả là "chiến thắng" khi $ p! = $ C (bạn chuyển sự lựa chọn của mình sang cánh cửa khác và bạn thắng).
Carlos Goce

0

Ngôn ngữ nhà sản xuất trò chơi, 19 (51 w / vòng)

show_message(200/3)

Nó cho ra 66,67! Đây là xác suất chính xác;)


Mã chế độ nghiêm trọng, 51 ký tự:

repeat(10000)p+=(random(1)<2/3);show_message(p/100)

Đảm bảo biên dịch với tất cả các biến chưa được khởi tạo là 0.


Mã cũ nhất, 59 ký tự:

for(i=0;i<10000;i+=1)p+=(random(1)<2/3);show_message(p/100)

Một lần nữa, hãy đảm bảo biên dịch với tất cả các biến chưa được khởi tạo là 0.

Đầu ra là 66.23

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.