Simule el problema de Monty Hall [cerrado]

8

Nunca he podido entender el problema de Monty Hall . Aquí está la premisa:

Suponga que está en un programa de juegos y le dan la opción de elegir entre tres puertas: detrás de una puerta hay un automóvil; detrás de los demás, cabras. Usted elige una puerta, dice No. 1, y el anfitrión, que sabe lo que hay detrás de las puertas, abre otra puerta, dice No. 3, que tiene una cabra. Luego te dice: "¿Quieres elegir la puerta número 2?" ¿Le conviene cambiar su elección?

Ejecute 10,000 simulaciones. Salida del porcentaje de ganancia de cambio. Por ejemplo:

> 66.66733%
bendytree
fuente
55
El anfitrión sabe dónde está el auto, por lo que nunca abre una puerta con el auto detrás de él
bendytree
66
Tal como está el desafío, es difícil argumentar que no es perfectamente legal tener solo 10,000 ejecuciones del generador de números aleatorios y sumar cuáles aterrizan por debajo de 0,6666. Se podría decir que en realidad no está simulando el problema de Monty Hall. Pero si produce exactamente la misma salida, ¿qué es lo que realmente falta?
breadbox el
Una interesante perspectiva histórica (sobre el problema, no el golf): ¿Qué puerta tiene el Cadillac? .
Cary Swoveland el
3
El desafío sigue siendo un poco ambiguo con respecto a las suposiciones que podemos hacer. Por ejemplo, algunas de las respuestas probablemente estén ahorrando una cantidad significativa de código al suponer que el automóvil estará detrás de la misma puerta cada vez o que el jugador elige la misma puerta cada vez.
Iszi
1
Enumerar todas las posibilidades es al menos tan esclarecedor como generarlas al azar ...
Daniel Cristofani

Respuestas:

4

JavaScript 52

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

Las puertas son 1: [0,1 / 3), 2: [1 / 3,2 / 3), 3: [2/3, 1)

Suponga que el premio siempre está en la puerta 3. Si el invitado elige las puertas 1 o 2, que es el rango [0,2 / 3), y cambia, ha ganado el premio.

Tristin
fuente
1
Parece que CoffeeScript nos permite eliminar un solo personaje:i=s=0;s+=Math.random()<2/3while i++<1e4;alert s/100
Kerrick
3

J: 17 15

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

Elige una puerta aleatoria (etiquetemos estos 0, 1 o 2 donde 2 es la puerta con el automóvil) y calcula el beneficio de cambiar según esta lógica:

  • Si el jugador eligió la puerta 0, el anfitrión abrirá la puerta 1. El cambio le otorgará al jugador un auto nuevo ( 1).
  • Si el jugador eligió la puerta 1, el anfitrión abrirá la puerta 0. El cambio le otorgará al jugador un auto nuevo ( 1).
  • Si el jugador eligió la puerta 2, la puerta ganadora, el anfitrión abrirá la puerta 0 o la puerta 1. De cualquier manera, si el jugador cambia, encontrará una cabra ( 0).

Luego calcula el resultado como la suma de la matriz anterior, dividida por 100.

Soy bastante inestable con J, así que estoy seguro de que esto podría mejorarse aún más.

pswg
fuente
3

R 115 100

La respuesta de pseudo-simulación tiene 23 caracteres de longitud:

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

pero aquí hay una simulación real:

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 son las posibles puertas
  2. S es una función para seleccionar aleatoriamente un elemento de un vector
  3. Ces la puerta con el auto (al azar entre D)
  4. Pes la puerta elegida por el jugador (al azar entre D)
  5. Hes la puerta elegida por el anfitrión (al azar entre Dmenos Cy P)
  6. Fes la puerta final elegida por el jugador (determinista: Dmenos Py H)
  7. El éxito se mide por C==F.

devuelve: [1] 66.731

Editar

Puedo guardar algunos caracteres al no asignar a variables y asumir sin pérdida de generalidad que 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
flodel
fuente
2

Perl, 98 89 83 75 72 71 caracteres

Aquí hay una respuesta seria que realmente ejecuta la simulación:

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

En cada iteración de bucle, la elección inicial del jugador es siempre la puerta # 2. Primero se almacena la puerta con el automóvil $%, luego se selecciona una puerta diferente para que Monty Hall la exponga. Si la puerta restante es igual a $%, se gana la ronda.

(Variables puncutation Perl $%y $=se utilizan porque se hacen número entero de truncamiento de forma gratuita.)

caja de pan
fuente
2

Powershell - 168 131 125 115

Código de golf:

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

Cambios del original: se
recortaron 53 caracteres del guión original con algunas modificaciones.

  • Se eliminaron espacios y paréntesis donde PowerShell lo perdona.
  • Usó un ForEach-Objectbucle, a través del %alias, en lugar de while.
  • Se utilizaron rangos de números (por ejemplo:) en 0..2lugar de matrices definidas explícitamente.
  • Eliminado writedel último comando: resulta que no lo necesito después de todo.
  • Volteó la expresión de la elección del host para usar la sintaxis de canalización más corta.
  • Reemplazado 10000 con 1e4.
  • Tomó la sugerencia de Joey y omitido Get-de Get-Random. (Nota: esta modificación aumenta significativamente el tiempo de ejecución. ¡En mi sistema saltó de unos 20 segundos a casi media hora por ejecución!)
  • Se utiliza el truco de Rynant de hacer $T+=...en lugar de if(...){$T++}.

Algunas notas:

Este guión pretende ser lo más conciso posible, a la vez que es una simulación tan completa del escenario de Monty Hall como sea posible. No hace suposiciones sobre dónde estará el auto o qué puerta elegirá el jugador primero. Ni siquiera se hacen suposiciones sobre qué puerta específica elegirá el host en un escenario dado. Las únicas suposiciones restantes son las que realmente se mencionan en el problema de Monty Hall:

  • El anfitrión elegirá una puerta que el jugador no eligió primero, que no contenga el automóvil.
    • Si el jugador abrió la puerta con el auto primero, eso significa que hay dos opciones posibles para el anfitrión.
  • La elección final del jugador no será ni su elección inicial ni la elección del anfitrión.

Sin golf, con comentarios:

# 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

He ejecutado este script varias veces y produce resultados consistentemente muy cercanos a dos tercios de probabilidad. Algunas muestras:

(Como anteriormente)

  • 67,02%

(Utilizando Get-Randomcomo la definición de alias, en lugar de solo Random)

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

Rubí 48 40 38

Mi código no hace suposiciones sobre qué puerta siempre estará detrás del premio o qué puerta abrirá siempre el jugador. En cambio, me concentré en lo que hace que el jugador pierda. Según el artículo de Wikipedia :

[...] 2/3 de las veces, la elección inicial del jugador es una puerta que esconde una cabra. Cuando ese es el caso, el anfitrión se ve obligado a abrir la otra puerta [...] de cabra "Cambiar" solo falla al ceder el auto cuando el jugador elige la puerta "correcta" (la puerta que oculta el auto) para empezar.

Entonces, para simular esto (en lugar de usar valores fijos), lo modelé así:

  • el programa elige al azar 1 de las 3 puertas para ocultar el premio
  • el jugador elige al azar 1 de las 3 puertas como su primera opción
  • el jugador siempre cambia, por lo que si su primera elección fue la misma que la del programa, pierde

El código v1:

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

El código v3 (¡gracias a steenslag e Iszi!):

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

Algunos valores de retorno de muestra:

  • 66,44
  • 66,98
  • 66,33
  • 67,2
  • 65,7
Jonathan Hefner
fuente
1
p (1..10000).count{rand(3)!=rand(3)}/1e2Guarda algunos caracteres.
steenslag
@steenslag Ah, de hecho lo hace! ¡Gracias! =)
Jonathan Hefner
1
¿Ruby no permite poderes de atajo de 10? Por ejemplo: 1e4para 10000?
Iszi
@Iszi Sí, pero la notación científica produce un flotador, por lo que no siempre se puede sustituir. Sin embargo, es una sustitución viable en v2, ¡ahorrando 2 caracteres más!
Jonathan Hefner
1

Mathematica 42

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

66,79

DavidC
fuente
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

Comentado:

# 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
Rynant
fuente
Esto no genera un porcentaje ganador en el formato especificado en la pregunta. Además, guarde un par de caracteres utilizando en 1e4lugar de 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);}

Eso es para la simulación real. Para algunos códigos de flexión de reglas engañosos, es solo 71 65 59:

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

No hice srand () porque las reglas no decían que tenía que hacerlo. Además, la versión engañosa imprime alrededor de 30,000 números adicionales porque guarda un personaje. Probablemente me faltan algunos trucos, pero hice lo mejor que pude.

Stuntddude
fuente
Se garantiza que las variables globales serán cero al inicio. Mueva sus declaraciones de variables mainy podrá eliminar las =0inicializaciones.
breadbox
1

Pitón 2: 72 66 64

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

Salida de ejemplo: 66.49

Rees
fuente
1
Puede guardar algunos caracteres utilizando en exec"i-=randint(0,2)&1;"*ilugar del forbucle.
Vuelve a instalar a Monica el
@WolframH Gracias, lo actualizaré ahora.
Rees
Además, use en print.01*ilugar de print i/100..
Reinstale a Monica el
Buena solución pero te falta un punto y coma.
Daniel Lubarov el
Muy cierto. Actualizando ahora ...
Rees
0

Pescado - 46 43

Esto está utilizando los mismos supuestos que Tristin hizo:

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

La dirección hacia abajo en xrepresenta que inicialmente seleccionó la puerta correcta, izquierda y derecha son los casos en que eligió una puerta diferente, y arriba no es nada, y rodará nuevamente.

Originalmente, comencé 10000con "dd"*, pero "dd"tenía que estar todos en la misma línea, y desperdicié algo de espacio en blanco. Al serpentear aa*a*a*pude eliminar una columna y, en última instancia, 3 caracteres. Queda un poco de espacio en blanco que no he podido eliminar, ¡creo que esto es bastante bueno!

Cruncher
fuente
0

PHP 140

Pero creo que esto no está funcionando bien. ¿Algún consejo? Estoy obteniendo valores de 49 a 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;
Carlos Goce
fuente
"Si el jugador cambia la selección"?
Timtech
Lo siento, mi inglés no es bueno. Quiero decir, primero hago un intento de obtener valores aceptables. Debido a que el "anfitrión" no puede quitar una puerta que contiene el automóvil O la puerta que usted elija. Luego tengo $ p (elección de los jugadores) y $ c (donde está el auto). El OP dijo que debes tomar el porcentaje de victorias cuando cambias, así que solo cuento el resultado como una "victoria" cuando $ p! = $ C (cambias tu elección a la otra puerta y ganas).
Carlos Goce
0

Game Maker Language, 19 (51 con bucle)

show_message(200/3)

¡Produce 66.67! Esta es la probabilidad correcta;)


El código de modo serio, 51 caracteres:

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

Asegúrese de compilar con tratar todas las variables no inicializadas como 0.


El código más antiguo, 59 caracteres:

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

Nuevamente, asegúrese de compilar con tratar todas las variables no inicializadas como 0.

La salida fue 66.23

Timtech
fuente