Я создал (довольно сложную) симуляцию Монти Холла на Python, но при запуске возвращает равные шансы 33% как для переключения, так и для нет, когда я знаю, что на самом деле этого не может быть, и это не так. Что случилось?

import math
import random

Right = 0
def TestWithSwitch():
    global Right
    wdoor = math.floor(random.random() * 3)
    doors = [0,0,0]
    doors[wdoor] = 1
    Ldoors = [0,0]
    i=0
    ##Declare winning door to be the winning door in the door Array

    for x in range(0, 3):
        if(x!=3):
            if(doors[x] != 1):
                Ldoors[i] = x
                i+=1
    ##Chose the losing doors to be the doors that aren't the winning door
    choice = math.floor(random.random() * 3)
    DoorOut = 0
    ##Pick a Choice
    LChose = False
    for y in range(0, 2):
        if(y!= 2):
            if(Ldoors[y] == choice):
                DoorOut = Ldoors[(y+1)%2]
                LChose = True
    if(LChose == False):
        DoorOut = Ldoors[math.floor(random.random() * 2)]
    Reserved = [DoorOut, choice]

##DoorOut is chosen from any of the losing doors we didn't pick as our choice, and is the door the computer is told doesn't have the prize
    for z in range(0, 3):
        if(z!= 3):
            if(z in Reserved == False):
                choice = z
                ##Make our new choice the other choice that we didn't previously choose
    if(choice == wdoor):
        Right+=1

def TestNoSwitch():
    global Right
    wdoor = math.floor(random.random() * 3)
    doors = [0,0,0]
    doors[wdoor] = 1
    Ldoors = [0,0]
    i=0


    for x in range(0, 3):
        if(x!=3):
            if(doors[x] != 1):
                Ldoors[i] = x
                i+=1
    choice = math.floor(random.random() * 3)
    if(choice == wdoor):
        Right+=1



for j in range(1, 10000):
    ## TestWithSwitch() and TestNoSwitch() both result in about 1/3. You can test by putting either function in.
    if(j == 9999):
        print(Right/10000)

Я знаю, что переключение должно давать шансы 66%, а не 33%. Шансы, которые я получаю, обычно составляют даже не 100%, а около двух третей, что является вероятной невозможностью.

0
Jonah 2 Янв 2018 в 03:49

2 ответа

Лучший ответ

Проблема здесь:

if(z in Reserved == False):

Это оценивается как цепное сравнение и всегда приводит к ложному результату.

if(z in Reserved and Reserved == False):

Используйте круглые скобки, чтобы создать правильный порядок операторов:

if((z in Reserved) == False):

Или лучше использовать явный оператор "не в":

if(z not in Reserved):
2
NineBerry 2 Янв 2018 в 01:41

Ну, во-первых,

for x in range(0, 3):
    if(x!=3):          # redundant: x will never be 3

Во-вторых, сбор результатов функции через глобальную переменную - зло.

Вот как бы я это сделал:

from random import choice

DOORS = "ABC"

def pick():
    """
    Return a door at random
    """
    return choice(DOORS)

def always_switch():
    """
    Monty Hall strategy - when offered a choice, always switch
    """
    guess = pick()
    actual = pick()
    return not guess == actual

def never_switch():
    """
    Monty Hall strategy - when offered a choice, never switch
    """
    guess = pick()
    actual = pick()
    return guess == actual

def test(fn, tries):
    """
    Return the fraction of calls to fn which return True
    """
    return sum(1 for _ in range(tries) if fn()) / tries

def main():
    """
    Simulate the Monty Hall problem
    """
    tries = 10000

    pct = 100. * test(always_switch, tries)
    print("Test (always switch): %0.1f %%" % (pct,))

    pct = 100. * test(never_switch, tries)
    print("Test (never switch): %0.1f %%" % (pct,))

if __name__ == "__main__":
    main()

Который производит вывод, как

Test (always switch): 66.3 %
Test (never switch): 32.7 %

Примечание: вы можете ускорить его, произвольно заменив guess = pick() на guess = "A" (без потери общности).

2
Hugh Bothwell 2 Янв 2018 в 01:29