Python Monty Hall Simulation didn't give expected answer - python

I get the answer 0.5 in the Monty Hall Simulation.
From the textbook: We assume the car was put behind a door by rolling a three-sided die which made all three choices equally likely. Monty knows where the car is, and always opens a door with a goat behind it. Finally, we assume that if Monty has a choice of doors (i.e., the contestant has picked the door with the car behind it),he chooses each door with probability 1/2. Marilyn clearly expected her readers to assume that the game was played in this manner.
Marilyn's answer is 0.66, and I want to simulate this answer, but I got 0.5 and don't know what's wrong with my codes.
n = 1000000
count = 0
for i in range(n):
doors = [1,2,3]
# the inital doors that monty can choose
monty_choose = [1,2,3]
# suppose the car is behind door 1
car = 1
# monty cannot choose the door that has car
monty_choose.remove(car)
ichoose = random.choice(doors)
if ichoose in monty_choose:
# monty cannot choose the door i select
monty_choose.remove(ichoose)
monty = random.choice(monty_choose)
else:
monty = random.choice(monty_choose)
# i cannot choose the door that monty chose
doors.remove(monty)
s = random.choice(doors)
if s == car:
count = count + 1
print(count/n)

Your code could work find until you get to the last bit. You are picking the door at random:
s = random.choice(doors)
if s == car:
count = count + 1
When what you want to do is to switch doors. You can do this by simply removing your first choice then indexing the list at 0.
doors.remove(ichoose)
if doors[0] == car:
count = count + 1
full code and result
import random
n = 1000000
count = 0
for i in range(n):
doors = [1,2,3]
# the inital doors that monty can choose
monty_choose = [1,2,3]
# suppose the car is behind door 1
car = 1
# monty cannot choose the door that has car
monty_choose.remove(car)
ichoose = random.choice(doors)
if ichoose in monty_choose:
# monty cannot choose the door i select
monty_choose.remove(ichoose)
monty = random.choice(monty_choose)
else:
monty = random.choice(monty_choose)
# i cannot choose the door that monty chose
doors.remove(monty)
doors.remove(ichoose)
if doors[0] == car:
count = count + 1
print(count/n)
0.667145

Your code calculates probability of 0.5 simply because s = random.choice(doors) is choosing from car or goat equally.
Your code does not reflect how the Monty Hall problem works.
If the contestant makes a choice and sticks with that choice, then the probability is obviously 0.33. You never allow ichoose to stick with their choice.
The less obvious part is that the contestant can change their choice and then the probability is 0.66. You never allow ichoose to change their choice.

doors = [1,2,3] # total doors
i_choose = [1,2,3] # the inital doors that I can choose
car = 1 # suppose the car is behind door 1
host_choose = [2,3] # the empty doors the host could show
n = 1000000
count = 0
car = 1
for i in range(n):
# you can randomize car here, but remember to change host_choose accordingly
i_choice = random.choice(doors) # I choose one door randomly
if first_choice in host_choose:
host_choose.remove(first_choice) # the host cannot open the chosen door
host_choice = random.choice(host_choose) # the host shows that a door is empty
i_choose.remove(host_choice)
i_choose.remove(first_choice)
# the goal is to show that always changing door results in 66% winrate
i_choice = random.choice(i_choose) # this is actually a one-element list
if i_choice == car:
count = count + 1
i_choose = [1,2,3]
doors = [1,2,3]
host_choose = [2,3]
print(count/n)
So basically, you're mixing up who and when does the choices:
A picks a door in [1, 2, 3]
B knows where the car is, and reveals an empty door (that A didn't pick)
A now can choose to keep their door or to change it
Your goal is to show that changing door leads to 0.66 probability of getting the car.

Related

Creating a simple family feud game with two players

I was doing a simple python game ( I'm new to programming, sorry if asked anything wrong ) where two players play and answer the questions.
Underlying principles of the game:
There are several possible answers that a player can guess from. Each possible answer has a certain amount of points associated with it. If the player guesses an answer that exists in the possible answers, they will be rewarded with the corresponding amount of points.
question = "Name something James Bond eats everyday"
possible_answers = [("LEMON/CITRUS", 25), ("KETCHUP/MUSTARD", 25), ("TOOTHPASTE", 19), ("ZIT/BLACKHEAD", 14), ("GLUE", 6), ("MY POOPER", 3), ("LOTION BOTTLE", 2), ("LIQUID SOAP/SHAMPOO", 2)]
# Test case 1
player answer: mustard
25
# Test case 2
player answer: mayonnaise
0
The player can continue guessing until they run out of strikes or they guess all the possible answers.
Each correct guess increases the player's score. The player loses a strike if they guess something that has already been guessed before or guess something that isn't in the set of possible answers.
# Test case 1
player answer: cry
player answer: cry some more
player answer: cry a lot
player answer: wake me at 3 am
player score: 39, player strikes left: 0
# Test case 2
player answer: cry
player answer: make mess
player answer: eat my candy
player answer: poo
player answer: fart
player answer: puke on me
player answer: pee
player answer: burp
player answer: nurse
player score: 98, player strikes left: 2
Here are the rules of the game:
First, we will assume that player 1 always gets the right to try to make the first guess.
If player 1 makes a correct first guess, they get control of the round. Otherwise, player 2 gets control of the round.
The player that has control of the round will keep guessing and collecting points until they guess all the possible answers. In this case, the round is over and the points are banked to the controlling player's account.
If the controlling player loses all their strikes before guessing all the answers, the other player gets a chance to steal the controlling player's points for the round.
If the other player makes a correct guess, all the points earned by the controlling player in the current round are banked to the other player's account.
If the other player makes an incorrect guess, all the points earned by the controlling player in the current round are banked to the controlling player's account.
Then the round ends.
When a player steals the points, they do not gain the points of their guess. They only gain the points that the controlling player collected for the current round.
Example Case:
question = "Name something a baby does that would be unacceptable in a roommate."
possible_answers = [("CRY/AT 3 A.M.", 39), ("POO/WET SELF", 28), ("PUKE/ON ME", 9), ("BURP", 8), ("MAKE MESS/TOSS FOOD", 5), ("FART", 4), ("PEE IN MY FACE", 3), ("NURSE/ON MY NIPS", 2)]
# Test case 1 - player 1 controls, gains 84 points, loses all 3 strikes, player 2 gets chance to steal but fails, player 1 wins round
player 1 answer: cry
player 1 answer: poo
player 1 answer: puke
player 1 answer: burp
player 1 answer: cry
player 1 answer: cry
player 1 answer: cry
player 2 answer: cry
player 1 score: 84, player 1 strikes left: 0, player 2 score: 0, player 2 strikes left: 3
# Test case 2 - player 1 controls, gains 84 points, loses all 3 strikes, player 2 gets chance to steal and succeeds, player 2 wins round
Here is what I already did:
question = "Name something a baby does that would be unacceptable in a roommate."
possible_answers = [("CRY/AT 3 A.M.", 39), ("POO/WET SELF", 28), ("PUKE/ON ME", 9), ("BURP", 8), ("MAKE MESS/TOSS FOOD", 5), ("FART", 4), ("PEE IN MY FACE", 3), ("NURSE/ON MY NIPS", 2)]
player_1_strikes_left = 3
player_2_strikes_left = 3
player_1_score = 0
player_2_score = 0
player_score = 0
match = False
player_1_answer = input("1: ")
player_2_answer = "000"
player_1_answer = player_1_answer.upper()
player_2_answer = player_2_answer.upper()
player_1_control = None
if player_1_answer.upper() != "ooooooooooooooooooooooo":
for item in possible_answers:
answer = item[0]
if player_1_answer in answer:
player_1_control = True
player_1_score += item[1]
possible_answers.remove(item)
match = True
break
else:
cplayer_1_control = False
else:
None
#if player_1_control != True
while player_1_score < 0 :
while player_1_control == True:
while player_1_strikes_left != 0 and len(possible_answers) != 0:
player_1_answer = input()
player_1_answer = player_1_answer.upper()
match = False
for item in possible_answers:
answer = item[0]
if player_1_answer in answer:
player_1_score += item[1]
possible_answers.remove(item)
match = True
break
#print(possible_answers)
if not match:
player_1_strikes_left -= 1
if player_1_strikes_left == 0:
player_1_control = False
else:
continue
break
while player_1_control == False :
while player_2_strikes_left != 0 and len(possible_answers) != 0:
player_2_answer = input()
player_2_answer = player_2_answer.upper()
match = False
for item in possible_answers:
answer = item[0]
if player_2_answer in answer:
player_2_score += item[1]
possible_answers.remove(item)
match = True
break
#print(possible_answers)
if not match:
player_2_strikes_left -= 1
if player_2_strikes_left == 0:
player_1_control = True
else:
continue
break
print(f'player 1 score: {player_1_score}, player 1 strikes left: {player_1_strikes_left}, player 2 score: {player_2_score}, player 2 strikes left: {player_2_strikes_left}')
I don't know why but the code runs infinitely and doesn't change the player when the other one runs out of strikes.
Thank you very much beforehand!

Determining winner in Rock Paper Scissors [python]

I'm a beginner in python trying to create a RPS game where human is playing against a computer. The game is created such that it would be played over a number of determined rounds (best of 3 rounds). A draw is considered a point for each side.
My problem is setting the while condition. Initially I did this:
while (player_count + computer_count) != winning_score : where the game ends when all round are played. However there will be instances where not all rounds needs to be played and the winner can already be determined (because of draws, each player will get a point).
How do I change the while condition such that when either players get winning_score/2 + 1, the game ends?
hi you can probably do it like this
winning_count = winning_score/2+1
while(player_count < winning_count) and (computer_count < winning_count):
...
Once either the player win or the computer win is more than the winning count, it goes to False and the loop breaks
Just in case you want to have another perspective on how to implement the game (and how to determine the winner), I exhort you to play with the following version:
import random
options = {1: 'Rock', 2: 'Scissors', 3: 'Paper'}
def play():
score = [0, 0]
while not any(wins == 3 for wins in score):
print(f'SCORE\tUser: {score[0]} - PC: {score[1]}')
user_selection = int(input('Enter your selection:{}> '.format(
''.join([f'\n{n}: {option}\n' for n, option in options.items()]))))
pc_selection = random.randint(1, 3)
print(f'{options[user_selection]} vs. {options[pc_selection]}')
if user_selection in (pc_selection - 1, pc_selection + 2):
print('User wins')
score[0] += 1
elif user_selection == pc_selection:
print('Draw')
else:
print('PC Wins')
score[1] += 1
input('\n_____ ENTER TO PROCEED _____')
winner = 'User' if score[0] == 3 else 'PC'
print(f'\n{winner} won the match!')
play()
Hopefully you will find here something useful and new for your learning process.

Probability Assimilation using python

I am trying to get some probability by simulating a game (assimilation) using python.
A and B play a game where they take turns to throw a coin (A starts first), and the first one to throw a head wins. But their coins are biased! A's coin has a 1 in 5 chance of coming up heads, and B's coin has a 1 in 3 chance of coming up heads.
The code should simulate it and answer this question: What is the probability of A winning if he goes first?
By solving through mathematically, I came to this solution: 3/7.
This is what I've done so far, but it doesn't give me the expected number.
import numpy as np
def P1_win_prob_weighted_coin_game(num_games, prob_heads=.5):
player_one_wins = 0
for n in range(0,num_games):
num_flips = 0
win = 0
while win == 0:
turn = np.random.uniform(0,1)
num_flips += 1
if turn <= prob_heads:
if num_flips % 2 != 0:
player_one_wins += 1
win += 1
return float(player_one_wins)/float(num_games)
What am I doing wrong?
I think I got it.
First, define a function that plays one game and tells me who the winner was.
def get_winner(prob_to_win=[1/5, 1/3]):
''' Tells who the winner was.
Params:
prob_to_win is a list with the probabilites of each player to win
Returns:
the index of the player who won (based on prob_to_win)
'''
number_of_players = len(prob_to_win)
while True:
for player in range(number_of_players):
coin_flip = np.random.uniform()
if coin_flip <= prob_to_win[player]:
return player
Next, define the names, probabilites and number of games to play (observeations)
player_names = ['A', 'B']
player_probs = [1/5, 1/3]
number_of_games = 500000
Let the games begin! (Note: for more verbosity, you can uncomment the print line)
player_win_count = [0, 0]
for i in range(number_of_games):
winner = get_winner(player_probs)
player_win_count[winner] += 1
# print(f'The winner was {player_names[winner]} ({player_win_count[winner]} wins so far)')
Finally, get and display the results.
for (player, wins) in zip(player_names, player_win_count):
chances = wins/number_of_games
print(f'Statistics (with {number_of_games} observations) tell that player {player} has {chances} chances to win against others')
Outputs:
Statistics (with 500000 observations) tell that player A has 0.427982 chances to win against others
Statistics (with 500000 observations) tell that player B has 0.572018 chances to win against others
Which is very close to the probability that you calculated 3/7.
Hope it helps! This was fun :)

Python not finishing for loop

I just started learning python and I figured for fun to see if I could make a python version of the monty hall problem. Everything seems to be working on a small scale when I use 1 or 2 iterations but past that nothing is working. The for loop is not finishing the amount of iterations I want it to.
import random
def problem(tests):
wins = 0
losses = 0
doors = ["goat", "car", "goat"]
for test in range(tests):
#we shuffle the doors
random.shuffle(doors)
#the player picks a door
choice = random.choice(doors)
#monty chooses a door
montychoice = random.choice(doors)
while montychoice != 'car' or montychoice == choice:
montychoice = random.choice(doors)
#if the player's door is a car, he losses
if choice == 'car':
losses += 1
print 'goat'
elif choice == 'goat':
wins += 1
print 'car'
print "Switching wins: %d" % wins
print "Switching loses: %d" % losses
problem(100)
The problem isn't with the for-loop, but with the while loop.
In order for your while loop to break, montychoice would have to equal car AND the player's choice. But what if the player's choice isn't car, but it's goat? The while-loop will never break.
I think you want and and not or for your while loop. That way, if either condition isn't met, the loop breaks.
The problem is this loop
while montychoice != 'car' or montychoice == choice:
montychoice = random.choice(doors)
Once the player has picked the car, this says that whether monty picks a car or not a car, he has to pick another choice. So he keeps on picking forever, and you don't get any further in your script.

Python Black Jack game variant

My Black Jack code is very basic but is running quite smoothly, however I have run into a speed bump. Thus im here. When I call "Hit" to send me another card in my While loop, for every loop the DECK instantiates the same card. The first 2 drawn and the Hit card are always different but within the While loop (which is set to end when the player says "stay" and doesnt want another card.) the Hit cards remain the same.
import random
import itertools
SUITS = 'cdhs'
RANKS = '23456789TJQKA'
DECK = tuple(''.join(card) for card in itertools.product(RANKS, SUITS))
hand = random.sample(DECK, 2)
hit = random.sample(DECK, 1)
print("Welcome to Jackpot Guesser! ")
c = input("Would you like to play Black Jack or play Slots? ")
if c == 'Black Jack':
print()
print("Welcome to Black Jack! Here are the rules: ")
print("Black Jack is a game of whit, skill with a bit of Luck. You will start with 2 card and try to achieve a total of 21 points. \n Each cards worth is equal to its number, face cards are worth 10 and the Ace can be 1 or 11 points. You decide. \n You can decide to -Stay- and take the points you have or -Hit- to get another card. If you get 21 its Black Jack and you win. \n If no one gets 21, the highest points win, but if you go over 21 you -Bomb- and lose everything. \n Becarful not to Bomb and goodluck out there! Remember, you got to know when to Hit, when to Stay and when to walk away! \n")
print(hand)
print()
g = 'swag'
while g != 'Stay':
g = input(("What would you like to do, Stay or Hit: "))
if g == 'Hit':
print(hit)
elif g == 'Stay':
print("Lets see how you did!")
else:
print("test3")
elif c == 'Slots':
print("test")
else:
print("test2")
EX: Hand: Td(two diamonds), 3c(3 club)
Hit: 7s(7 spades)
hit 7s
hit 7s
hit 7s
...
stay: lets see how you did. I need the continued While loop Hits to differ, any ideas.
The problem is that you are generating the hit card only once, during the start of the program. Changing your code from
if g == 'Hit':
print(hit)
to something like
if g == 'Hit':
hit = random.sample(DECK, 1)
print(hit)
will make it outputs different cards on each hit.

Categories

Resources