モンティホール問題のシミュレーション[終了]


8

モンティホール問題に頭を抱えることはできませんでした。ここに前提があります:

ゲームショーに参加していて、3つのドアの選択肢が与えられているとします。1つのドアの後ろには車があります。他の後ろに、ヤギ。あなたはドアを1つ選びます。ドアの後ろに何があるかを知っているホストが、山羊のいる3つ目のドアを開けます。それから彼はあなたに「2番のドアを選びたいですか?」選択を切り替えることはあなたにとって有利ですか?

10,000シミュレーションを実行します。スイッチングの勝率を出力します。例えば:

> 66.66733%

5
ホストは車がどこにあるか知っているので、後ろに車があるドアを開けることはありません
— bendytree

6
困難な状況が続く中、乱数ジェネレーターを10,000回実行するだけで0.6666未満に到達するものを合計することは完全に合法ではないと主張することは困難です。モンティホールの問題を実際にシミュレートしているのではないと言うかもしれません。しかし、それがまったく同じ出力を生成する場合、実際には何が欠けているのでしょうか?
— ブレッドボックス2013年

興味深い歴史的視点(ゴルフではなく問題について):キャデラックはどのドアですか?。
— Cary Swoveland 2013年

3
私たちがどのような仮定をすることを許可されているかに関して、課題はまだ少し曖昧です。たとえば、回答のいくつかは、車が毎回同じドアの後ろにある、またはプレイヤーが毎回同じドアを選ぶと想定することにより、おそらくかなりの量のコードを節約しています。
— Iszi

1
すべての可能性を列挙することは、少なくともそれらをランダムに生成することと同じくらい
— 明快

回答:


4

JavaScript 52

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

ドアは1:[0,1 / 3)、2:[1 / 3,2 / 3)、3:[2/3、1)です。

賞は常にドア3にあると仮定します。ゲストがドア1または2(範囲[0,2 / 3))を選択し、それらが切り替わった場合、彼らは賞を獲得しました。


1
CoffeeScriptのように見えますが、単一の文字剃り落とすに私たちをことができます:i=s=0;s+=Math.random()<2/3while i++<1e4;alert s/100
— Kerrick

3

J:17 15

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

ランダムなドアを選び(これらに0、1、または2のラベルを付け、2は車のドアです)、このロジックに基づいて切り替えの利点を計算します。

  • プレイヤーがドア0を選んだ場合、ホストはドア1を開きます。切り替えると、プレイヤーに新しい車が獲得されます(1)。
  • プレイヤーがドア1を選んだ場合、ホストはドア0を開き1ます。切り替えにより、プレイヤーは新しい車を獲得します()。
  • プレイヤーがドア2、勝ちのドアを選んだ場合、ホストはドア0またはドア1のいずれかを開きます。どちらにしても、プレーヤーが切り替わると、山羊を見つけます(0)。

次に、前の配列の合計を100で除算して結果を計算します。

私はJとかなり不安定なので、これをさらに改善できると確信しています。


3

R 115 100

擬似シミュレーション答えは23文字の長さ:

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

しかし、これは実際のシミュレーションです:

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 可能なドアです
  2. S ベクトルから1つのアイテムをランダムに選択する関数です
  3. C車のドアです(ランダムD)
  4. Pプレイヤーが選んだドアです(の間でランダムD)
  5. Hホストによって選択されたドアです(DマイナスCとの間でランダムP)
  6. Fプレイヤーが選択した最後のドアです(確定的:DマイナスPとH)
  7. 成功はによって評価されC==Fます。

戻り値:[1] 66.731

編集する

変数に割り当てず、一般性を失うことなく次のように仮定することで、いくつかの文字を節約できます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文字

実際にシミュレーションを実行する深刻な答えは次のとおりです。

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

各ループの繰り返しでは、プレイヤーの最初の選択は常にドア#2です。最初に車のあるドアがに保管され$%、次にモンティホールが公開する別のドアが選択されます。残りのドアがに等しい場合、$%ラウンドが勝ちます。

(Perlのパンクチュエーション変数は$%、$=整数の切り捨てを無料で行うために使用されます。)


2

PowerShellの- 168 131 125 115

ゴルフしたコード:

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)%"

オリジナルからの変更:
元のスクリプトから53文字をトリミングして変更しました。

  • PowerShellで許容されるスペースと括弧が削除されました。
  • の代わりにForEach-Object、%エイリアスを介してループを使用しましたwhile。
  • 0..2明示的に定義された配列の代わりに番号範囲(例:)を使用しました。
  • write最後のコマンドから削除されました-結局私はそれを必要としません。
  • 短いパイプライン構文を使用するために、ホストの選択式を反転させました。
  • 10000を1e4に置き換えました。
  • 取ったジョーイの提案を省略Get-からGet-Random。(注:この変更により、実行時間が大幅に膨張します。私のシステムでは、実行ごとに約20秒から30分近くにジャンプしました!)
  • 代わりに、Rynantのトリックを使用しました。$T+=...if(...){$T++}

いくつかのメモ:

このスクリプトは、モンティホールのシナリオをできるだけ完全にシミュレーションしながら、できるだけ簡潔にすることを目的としています。車がどこにあるのか、どのドアがプレイヤーが最初に選択するのかは想定していません。ホストがどの特定のシナリオで選択する特定のドアについても、想定は行われません。残りの仮定は、Monty Hall問題で実際に述べられているものだけです。

  • ホストは、プレイヤーが最初に選択しなかったドアを選択します。ドアには車が含まれていません。
    • プレイヤーが最初に車でドアを選んだ場合、それはホストに2つの可能な選択肢があることを意味します。
  • プレーヤーの最終選択は、彼の最初の選択でもホストの選択でもありません。

コメントなしのゴルフ場:

# 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

このスクリプトを何度か実行しましたが、結果は常に3分の2に近い確率で結果を出力します。いくつかのサンプル:

(上記のように)

  • 67.02%

(Get-Random単にの代わりに、エイリアス定義として使用Random)

  • 66.92%
  • 67.71%
  • 66.6%
  • 66.88%
  • 66.68%
  • 66.16%
  • 66.96%
  • 66.7%
  • 65.96%
  • 66.87%

2

ルビー48 40 38

私のコードでは、賞品が常に後ろになるドアや、プレイヤーが常に開くドアについては想定していません。代わりに、プレイヤーを失う原因に焦点を当てました。あたりとしてウィキペディアの記事:

[...]時間の2/3、プレーヤーの最初の選択は、山羊を隠すドアです。その場合、ホストは他のヤギのドアを開くように強制されます[...]「切り替え」は、プレーヤーが最初に「右」のドア(車を隠すドア)を選んだときにのみ車に与えることができません。

(これを固定値を使用する代わりに)シミュレートするために、次のようにモデル化しました。

  • ショーはランダムに3つのドアの1つを選び、賞品を隠します
  • 次に、プレイヤーはランダムに3つのドアの1つを最初の選択肢として選択します。
  • プレーヤーは常に切り替わるので、最初の選択が番組の選択と同じである場合、彼は負けます

コードv1:

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

コードv3(stenslagとIsziに感謝!):

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

戻り値の例:

  • 66.44
  • 66.98
  • 66.33
  • 67.2
  • 65.7

1
p (1..10000).count{rand(3)!=rand(3)}/1e2いくつかの文字を節約します。
— steenslag 2013

@steenslagああ、確かにそうです!ありがとうございました!=)
— ジョナサンヘフナー、

1
Rubyは10のパワーのショートカットを許可していませんか?例えば:1e4のため10000?
— Iszi

@Isziありますが、科学表記は浮動小数点数を生成するため、常に置換することはできません。ただし、これはv2で実行可能な置換であり、さらに2文字を節約できます。
— ジョナサンヘフナー、

1

Mathematica 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

コメント:

# 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

これは、質問で指定された形式で勝率を出力しません。また、1e4ではなくを使用して、数文字を保存し10000ます。
— Iszi 2013年

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);}

実際のシミュレーション用です。いくつかの不正なルールを曲げるコードでは、それは71 65 59です:

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

ルールは私がしなければならないと言っていなかったので、私はsrand()をしませんでした。また、チートバージョンでは文字を節約できるため、約30,000の余分な数字が出力されます。私はおそらくかなりの数のトリックを逃していますが、私はできる限りのことをしました。


グローバル変数は、起動時にゼロになることが保証されています。変数宣言を外に移動するmainと、=0初期化を削除できます。
— ブレッドボックス2013年

1

Python 2:72 66 64

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

出力例:66.49


1
ループのexec"i-=randint(0,2)&1;"*i代わりにを使用すると、いくつかの文字を保存できforます。
— モニカ

@WolframHありがとう、今すぐ更新します。
— リース

また、のprint.01*i代わりに使用してくださいprint i/100.。
— モニカを

良い解決策ですが、セミコロンがありません。
— ダニエルルバロフ2013年

とても本当です。今すぐ更新しています...
— Rees

0

魚 - 46 43

これはトリスティンが作ったのと同じ仮定を使用しています:

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

下方向は、x最初に正しいドアを選んだことを表します。左と右は、別のドアを選んだ場合で、上は何もないので、再び動きます。

もともとはで初期化10000しまし"dd"*た"dd"が、すべて同じ行になければならず、空白文字を無駄にしていました。蛇行aa*a*a*することで、列、そして最終的には3文字を削除することができました。私が取り除くことができなかった余白が少し残っていますが、これはかなり良いと思います!


0

PHP 140

しかし、私はこれが正しく機能していないと思います。ヒントは?49から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;

「プレイヤーが選択を変更した場合」?
— Timtech 2013年

すみません、私の英語は下手です。つまり、まず許容できる値を取得しようとする間、「ホスト」は、車が入っているドアや選択したドアを削除できないためです。それから私は$ p(プレイヤーの選択)と$ c(車がどこにあるか)を持っています。OPは、切り替えるときに勝利の割合をとる必要があると言ったので、$ p!= $ cのときだけ結果を「勝利」として数えます(選択を他のドアに切り替えて勝つ)。
— Carlos Goce 2013年

0

ゲームメーカー言語、19(51 w /ループ)

show_message(200/3)

66.67を出力します。これは正しい確率です;)


シリアスモードコード、51文字:

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

必ず、初期化されていないすべての変数を0として処理してコンパイルしてください。


最も古いコード、59文字:

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

ここでも、初期化されていないすべての変数を0として処理してコンパイルするようにしてください。

出力は 66.23

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.