Mostly because I didn't believe the outcome of the classic game play Make-a-Deal (see https://math.stackexchange.com/questions/608957/monty-hall-problem-extended) I made this little program... and indeed if there are 3 doors and the quiz-master opens a door and you then switch from your initial choice of door your chances go up from 33% to 67%! This program is the generalized version whereby you can choose the number of doors and how many doors the quiz-master will open, it calculates the chance for a price for the initial choice (basically 1 over the number of doors) and the chance if you change your selected door after the doors have been opened.
I was pleasantly taken by the elegant solution using Python sets, but I wonder if this is the most efficient way. Comparing with other methods it looks like it becomes relatively more efficient with more doors and doors to open.
Thank you for your input...
#!/usr/bin/env python
''' application of Make a deal statistics
application is using sets {}
for reference:
https://math.stackexchange.com/questions/608957/monty-hall-problem-extended
'''
import random
def Make_a_Deal(doors, doors_to_open):
''' Generalised function of Make_a_Deal. Logic should be self explanatory
Returns win_1 for the option when no change is made in the choice of
door and win_2 when the option to change is taken.'''
win_1, win_2 = False, False
doors_set = set(range(1, doors+1))
price_set = set(random.sample(doors_set, 1))
choice1_set = set(random.sample(doors_set, 1))
open_set = set(random.sample(doors_set.difference(price_set).
difference(choice1_set), doors_to_open))
choice2_set = set(random.sample(doors_set.difference(open_set).
difference(choice1_set), 1))
win_1 = choice1_set.issubset(price_set)
win_2 = choice2_set.issubset(price_set)
return win_1, win_2
def main():
''' input:
- throws: number of times to Make_a_Deal (must be > 0)
- doors: number of doors to choose from (must be > 2)
- doors_to_open: number of doors to be opened before giving the option
to change the initial choice (must be > 0 and <= doors-2)'''
try:
throws = int(input('how many throws: '))
doors = int(input('how many doors: '))
doors_to_open = int(input('how many doors to open: '))
if (throws < 1) or (doors < 3) or \
(doors_to_open > doors-2) or (doors_to_open < 1):
print('invalid input')
return
except Exception as e:
print('invalid input: ', e)
return
number_of_wins_1, number_of_wins_2, counter = 0, 0, 0
while counter < throws:
win_1, win_2 = Make_a_Deal(doors, doors_to_open)
if win_1:
number_of_wins_1 += 1
if win_2:
number_of_wins_2 += 1
counter += 1
print('completion is {:.2f}%'.
format(100*counter/throws), end='\r')
print('number of wins option 1 is {:.2f}%: '.
format(100*number_of_wins_1/counter))
print('number of wins option 2 is {:.2f}%: '.
format(100*number_of_wins_2/counter))
if __name__ == '__main__':
main()