pm21-dragon/exercises/release/exercise-12/3__Monty_Hall_problem.ipynb
2025-01-17 08:35:03 +01:00

9.9 KiB

None <html> <head> </head>

The Monty Hall problem (Deutsch: Ziegenproblem)

Read about it on Wikipedia or in German as the Ziegenproblem and come back. I'll wait.

In this notebook, you will write a program to simulated the Monty Hall problem.

We are going to make extensive use of the function random.randint(a, b). From its docstring, it returns a random integer in range [a, b], including both end points.

In [ ]:
import random
In [ ]:
for i in range(10):
    print(random.randint(0,2))

Q1

For your first task, create a function called sample_not which takes two positional arguments (call them not1 and not2) and will return a random integer between 0 and 2 (endpoints included) but which is not either of the arguments. The positional arguments will always be integers between 0 and 2 (inclusive).

In [ ]:
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
# This is a test of the above, do not change this code.
assert sample_not(0,1)==2
assert sample_not(0,2)==1
assert sample_not(1,0)==2
assert sample_not(1,2)==0
assert sample_not(2,0)==1
assert sample_not(2,1)==0
assert sample_not(0,1)==2
assert sample_not(0,0) in (1,2)
assert sample_not(1,1) in (0,2)
assert sample_not(2,2) in (0,1)

Q2

For your next task, consider the following code:

# generate what is behind the doors
doors = ['goat', 'goat', 'goat']
car_door = random.randint(0,2)
doors[car_door] = 'car'

# Now, the guest makes a first guess.
guess1 = random.randint(0,2)

# Now, the host opens a door, which is not the guess or the car.
host_open_door = sample_not(guess1,car_door)

# Based on the variable `do_switch` (which is not set here), the guess will either make a new choice or stay with the original guess.
if do_switch:
    guess2 = sample_not(guess1,host_open_door)
    final_guess = guess2
else:
    final_guess = guess1

# Finally, determine what was behind the door for the final guess.
result = doors[final_guess]

Put this code in a function called run_game which takes a single argument, do_switch, and returns a boolean, indicating a win with True or a loss with False.

In [ ]:
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
# This is a test of the above, do not change this code.
count = 300
for do_switch in (True, False):
    wins = 0
    for i in range(count):
        this_run_win = run_game(do_switch)
        assert(type(this_run_win)==bool)
        wins += int(this_run_win)
    print('do_switch: %s, wins: %d, count: %d'%(do_switch, wins, count))
    if do_switch:
        assert  abs(wins/count - 2/3) < 0.1
    else:
        assert abs(wins/count - 1/3) < 0.1

Note the above results. You have numerically simulated the Monty Hall problem.

Q3

Make a new game where there are 100 doors and the host opens 98 of them after the initial guess. Make a new function called run_game_100, and any other functions you need, which plays a single round of this game. Again, this function should take an argument do_switch.

In [ ]:
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
# This is a test of the above, do not change this code.
count = 1000
for do_switch in (True, False):
    wins = 0
    for i in range(count):
        this_run_win = run_game_100(do_switch)
        assert(type(this_run_win)==bool)
        wins += int(this_run_win)
    print('do_switch: %s, wins: %d, count: %d'%(do_switch, wins, count))
    if do_switch:
        assert abs(wins/count - 0.99) < 0.02
    else:
        assert abs(wins/count - 0.01) < 0.02
</html>