Monty hall simulation returning 50% odds? - python

from random import randint
numberOfDoors = 3
success = 0
attempts = 0
while True:
try:
doors = [0] * numberOfDoors
doors[randint(0, numberOfDoors - 1)] = 1
chosen = randint(0, numberOfDoors - 1)
while numberOfDoors > 2:
notIn = -1
while notIn == -1:
index = randint(0, numberOfDoors - 1)
if doors[index] == 0 and index != chosen:
notIn = index
if notIn < chosen:
chosen -= 1
del doors[notIn]
numberOfDoors -= 1
# doors is 2, so not chosen (0 or 1) will return the opposite (1 or 0)
success += doors[not chosen]
attempts += 1
if attempts % 1000000 == 0:
print float(success) / float(attempts)
except KeyboardInterrupt:
print float(success) / float(attempts)
break
My results are almost exactly 50% after a few hours of simulation - am I doing something specifically wrong?
Theoretically the door you choose is between 1/3 odds and 2/3 odds, so you should get higher than 50 at the very least.
This answer seems to do the same thing as me (ignoring that he doesn't do anything about monty's choice - I wanted to illustrate the concept).

You're forgetting to reset numberOfDoors (number of doors still closed, right?) back to 3. Since every iteration of the first while True: represents a new game show run, the show starts with all three doors initially closed.
...
while True:
numberOfDoors = 3
try:
doors = [0] * numberOfDoors
doors[randint(0, numberOfDoors - 1)] = 1
...
Next time, try adding print statements to help you debug. In this case, adding print doors right after you assign a car shows that doors has only two elements after the first iteration.

I wrote a Monty Hall simulation problem myself a while ago. Maybe it will help you with your code - in particular the comments may be useful:
from __future__ import division
import random
results = [] # a list containing the results of the simulations, either 'w' or 'l', win or lose
count = 0
while count <200: #number of simulations to perform
l = []
prize = random.randint(1, 3) #choose the prize door
initialchoice = random.randint(1, 3) #make an initial choice (the door the contestant chooses)
exposed = random.randint(1, 3) #choose the exposed door (the door the host chooses)
while exposed == initialchoice or exposed == prize: #make sure exposed is not same as prize or the initial choice
exposed = random.randint(1, 3)
if initialchoice != prize:
results.append('l') #if the initial choice was incorrect, append 'l'
else:
results.append('w') #if the initial choice was correct, append 'w'
count += 1
print 'prize door:', prize, 'initial choice:',initialchoice, 'exposed door:',exposed #print the results of the simulation
print
w = 0
for i in results:
if i == 'w':
w += 1
print w/len(results) #fraction of times sticking with the original door was successful

Related

Python if statement with multiple condition is messing up?

I'm a beginner with Python. I have a 2-d array called infected that stores values that correspond with the index. This bit of code is messy, but basically what I'm trying to do is simulate an infectious disease spreading over a number of days (T). The individual is infectious for infTime many days and then goes into recovery where they are immune for immTime days. There's also a probability value for whether a node will be infected and a value for how many nodes they will be connected to.
My problem is that I'm also trying to track the number of individuals currently susceptible, infected, or immune, but something is going wrong in the elif statement that is marked "# Messing up in this loop". Currently, the program is running through the statement more times than it should, which is throwing off the variables. If I switch the conditions in the elif statement, the program doesn't go through it and will stay at a very low number of infected individuals the entire time. I'm really stuck and I can't find any reason why it's not working how I want it to.
Code:
# Loop through T days, checking for infected individuals and connecting them to beta num of nodes, possibly infecting
infTime = 5 # Time spent infected before becoming immune
immTime = 20 # Time spent immune before becoming susceptible again
numSus = N - count
day = 0
while day < T:
for a in range(len(infected)):
nextnode = random.randint(0, N-1)
if((infected[a][0] == 1) and (infected[a][3] < infTime)):
num = infected[a][1]
for b in range(num-1):
if((a != nextnode) and (infected[nextnode][0] == 0)):
infected[a][3] += 1
chance = round((random.uniform(0, 1)), 2)
if(infected[nextnode][2] > chance):
infected[nextnode][0] = 1
G.add_edge(a, nextnode)
count += 1
numInf += 1
numSus -= 1
elif((a != nextnode) and (infected[nextnode][0] == 1)):
G.add_edge(a, nextnode)
elif((infected[a][0] == 1) and (infected[a][3] == infTime)): # Messing up in this loop
infected[a][3] = 0
infected[a][4] = 1
numImm += 1
numInf -= 1
G.add_edge(a, nextnode)
elif((infected[a][0] == 0) and (1 < infected[a][4] < immTime)):
infected[a][4] += 1
elif((infected[a][0] == 0) and (infected[a][4] == immTime)):
infected[a][4] = 0
numImm -= 1
numSus =+ 1
day += 1
print("Number of infected on day ", day, ": ", count)

Python task. Converting for to while

I just began programming and one of the tasks i got was making code that gives out prizes depending on the laps done. I began completing the exercise without realizing that i should be using a while loop in it, so here it is and i don't know how to make it work with a while loop.
to = int(input("Laps: "))
start = 1
prize = 0
for i in range(start, to+1):
if i % 2 == 0:
prize = prize + i
print("Prize: " + str(prize))
This should do it:
to = int(input("Laps: "))
i = 1
prize = 0
while i < (to+1):
if i % 2 == 0:
prize = prize + i
i = i + 1
print("Prize: " + str(prize))
It is essentially the same as your for loop. The main difference is that in a while loop you have to update the progress of your loop yourself, which is what the statement i = i + 1 is for.

How can I calculate the probability that two players different abilities will win a PARS squash game against each other? (Python)

I've created a function winProbability(ra, rb, n) and I want to simulate n games in order to estimate the probability that a player with the ability ra will win a game against a player with ability rb
I'll show the code I've done so far. If this seems like a easy issue it's because I am new to coding.
import random #import random allows for the use of randomly generated numbers
def game(ra, rb): #this function game sets out the way the game runs
p_a_point = ra/(ra+rb) #this line of code determines the probability that
#player a wins any given point
a_points = 0 #the amount of points player a has is defaulted to 0
b_points = 0 #the amount of points player b has is defaulted to 0
score_to_win = 11 #the winning score is defaulted to 11
while (a_points < score_to_win and b_points < score_to_win) or abs (a_points - b_points) < 2: #while player a's points and player b's points are less than the winning score:
p_b_point = random.random()#the probability b wins a point is set the a random value between 0 and 1
if p_b_point < p_a_point: #is the probability b wins a point is less than the probability a wins a point:
a_points = a_points + 1 #a wins 1 point
else: #if player a doesn't win a point:
b_points = b_points + 1 #b wins a point
return(a_points, b_points)#both players points are returned
print(game(70,30))#the function is called with two integer values as parameters
def winProbability(ra, rb, n):
To be honest from here I am unsure on how to go about this. I was thinking of doing a for loop so for example:
for n in game (ra, rb):
but I am unsure if I can use a previous function in this loop call. I'm also confused on how to calculate probabilities in code
The general aim is to call the function with two probabilities for example 70 and 30 and give a decimal answer for the probability player ra will win.
To previous commenters, I apologise for being vague before. I've never posted on here before.
See if this helps.
from random import randint, seed
seed()
rounds = input(" How many rounds will be played in the match? ")
print("\n Please enter skill levels as integers from 0 to 99.\n")
a = input(" What is the skill level of player 1? ")
b = input(" What is the skill level of player 2? ")
# Catch empty inputs
if not rounds: rounds = 10
if not a: a = 0
if not b: b = 0
# Python inputs are always strings. Convert them to integers.
rounds = int(rounds)
a = int(a)
b = int(b)
# If both skill levels are 0, set them to 1.
# (This will avoid a possible division by zero error.)
if a+b == 0: a = b = 1
# Catch and correct numbers that are too high.
if a > 99: a = 99
if b > 99: b = 99
# Convert integer skill levels to values between 0.0 and 0.99
a = a/100
b = b/100
print()
print(" Chance player 1 will win: "+str(int(100*a/(a+b)))+" percent.")
print(" Chance Player 2 will Win: "+str(int(100*b/(a+b)))+" percent.")
print()
for x in range(rounds):
roll = randint(0,999)/1000
print("roll =",roll, end =": ")
if roll <= a/(a+b): # <-- Compare roll to ratio of player skill levels.
print("Round "+str(x+1)+" Winner: Player 1")
else:
print("Round "+str(x+1)+" Winner: Player 2")
print()
this was my answer
import random
def winProbability(ra, rb, n):
winCount = 0 #used to count how many times 'a' won
probabilityRange = ra + rb
for i in range(n):
# pick a number between 0 and probabiilityRange
number = random.randint(0, probabilityRange)
# if number is < ra then 'a' won if number is > ra then 'b' won if number == ra then results in a draw
if number < ra:
winCount += 1
print ('win')
if number > ra:
print('loss')
if number == ra:
print ('draw') # draw doesn't count as win
return winCount*(100/n)
print (winProbability(10000,1,100000))
This prints the results of each game played, and returns the possibility that 'a' will win in percentile form.

Is there a way I could optimize multiple python for loops?

I am trying to make a multiplayer web game, I have a server done in python. Since the game is multiplayer, I need to update each player individually; This requires for loops, at the moment my code uses a lot of for loops, which is causing me some unwanted side affects. The side affects includes slowed speeds. Another issue i have with for loops is they change speeds depending on how many things they are looping through; This is causing problems with the fact that the number of items that the loop needs to loop through changes depending on how many players are connected, thus messing up the client side prediction function I made to mask lag.
This is my main code:
PlayerData = {}
for Player in Players:
if(Player.id > 50):
PlayerData['playerx' + str(Player.id)] = Player.x
PlayerData['playery' + str(Player.id)] = Player.y
PlayerData['playera' + str(Player.id)] = int(Player.angle)
PlayerData['playerstat' + str(Player.id)] = Player.alive
if(Player.id > 50):
if(Player.alive == 0):
Players.remove(Player)
for ID in clientIds:
PlayerData['id'] = str(clientIds[len(clientIds) - 1].id)
PlayerData['players'] = ids
if(Player.id <= 50):
hrIds.append(Player.id)
PlayerData['hx' + str(Player.id)] = Player.x
PlayerData['hy' + str(Player.id)] = Player.y
#PlayerData['ha' + str(Player.id)] = int(Player.angle)
PlayerData['hr'] = hrIds
PlayerJsonData = json.dumps(PlayerData)
await websocket.send(PlayerJsonData)
recivedData = await websocket.receive()
rData = json.loads(recivedData)
for ID in clientIds:
if(rData['id'] == str(ID.id)):
if(ID.IG == 0):
if(rData['playerstat'] == 1):
Players.append(player_classes.Basic(-1300, -1300, ID.ws, ID.id, 1))
ID.IG = 1
for Player in Players:
for Player2 in Players:
if(Player.id > 50):
Player.detect_collide(Player2)
if(rData['id'] == str(Player.id)):
if(rData['direction'] == "up"):
Player.accelerate(rData['direction'])
Player.moveUp(Player2)
if(rData['direction'] == "left"):
Player.accelerate(rData['direction'])
Player.moveLeft(Player2)
if(rData['direction'] == "down"):
Player.accelerate(rData['direction'])
Player.moveDown(Player2)
if(rData['direction'] == "right"):
Player.accelerate(rData['direction'])
Player.moveRight(Player2)
if(rData['direction'] == "none"):
Player.decelerate(rData['direction'])
EDIT: My main looping speed issue happens when I add more classes to Players
You should avoid checking the collision of the same pair of players twice.
Let's take a very simple example with Players list containing 0, 1, 2, 3.
With your code you get a lot of redundant tests:
At loop 0 you test 0 against 1, 2 and 3
At loop 1 you test 1 against 0, 2 and 3 ===> (but 0-1 was already tested)
At loop 2 you test 2 against 0, 1 and 3 ===> (but 0-2 / 1-2 were already tested)
At loop 3 you test 3 against 0, 1 and 2 ===> (but 0-3 / 1-3 / 2-3 were already tested)
So instead of:
for Player in Players:
for Player2 in Players:
Do:
for i, Player in enumerate(Players):
for Player2 in Players[i + 1:]:
If we use the list containing 0, 1, 2, 3 once again, we have the following behavior:
At loop 0 you test 0 against 1, 2, 3
At loop 1 you test 1 against 2, 3
At loop 2 you test 2 against 3
This way, it cuts the number of iterations from N^2 to N(N-1)/2.

How would I find the winner of my Python Tic Tac Toe game?

So far, I have a program where 2 players can click to place an X and an O in turns. I'm not sure how to make the program recognize a winner/ draw. If you guys could help me make a function that indicated a win/ draw on the screen in any way, I would love you forever. Thanks.
from graphics import *
import sys
def player_o(win, center):
'''
Parameters:
- win: the window
'''
outline_width = 5
circle = Circle(center, boxsize/2)
circle.setOutline('red')
circle.setWidth(outline_width)
circle.draw(win)
def player_x(win, p1x, p1y):
'''
Parameters:
- win: the window
'''
for i in range(2):
deltaX = (-1) ** i * (boxsize / 2)
deltaY = (boxsize / 2)
line = Line(Point(p1x - deltaX, p1y - deltaY),
Point(p1x + deltaX, p1y + deltaY))
line.setFill('red')
line.setWidth(5)
line.draw(win)
def game():
global win
global boxsize
try:
winsize = int(input("How large would you like the window? (Between 100 and 3000): "))
if winsize < 100 or winsize > 3000:
print("Invalid window size")
quit()
squares = int(input("How many squares per row? (Between 3 and 10):"))
boxsize = winsize/ squares
if squares < 3 or squares > winsize / 10:
print("Invalid number")
quit()
except ValueError:
sys.exit("Not a valid number")
win = GraphWin("Tic Tac Toe", winsize, winsize)
for i in range(squares - 1):
hline = Line(Point(0, (winsize/squares) * (i + 1)), Point(winsize, (winsize/squares) * (i + 1)))
hline.draw(win)
vline = Line(Point((winsize/squares) * (i + 1), 0), Point((winsize/squares) * (i + 1), winsize))
vline.draw(win)
for i in range((squares ** 2) // 2):
print("X, click a square.")
p1mouse = win.getMouse()
p1x = p1mouse.getX()
p1y = p1mouse.getY()
player_x(win, p1x, p1y)
print("O, click a square.")
p2mouse = win.getMouse()
p2x = p2mouse.getX()
p2y = p2mouse.getY()
player_o(win, Point(p2x, p2y))
if squares % 2 == 1:
print("X, click a square.")
p1mouse = win.getMouse()
p1x = p1mouse.getX()
ply = p1mouse.getY()
player_x(win, p1x, p1y)
game()
Keep data and representation of data separated. That's how. Right now you're just drawing things, rather than that you should be generating some representation of the playing field (e.g. a list of the boxes and their state, as in, checked by p1, checked by p2, or unchecked), and then use that to draw when needed. The advantage should be immediately obvious - if you know the state of the game, determining if there's a winner (and who it is) is trivial.
After 3 turns (minimum turns to win) check your 2d array if there is a token next to the last played by adding/substracting one, if found repeat same operation to array indices else break out.
If 2nd control structure is reached break and announce winner.
With each move in the game, a 2D array or a dictionary (with values being lists) should be used. Then, you can just check each way of winning. This way, you can also check if the move is valid or not--- whether or not the spot on the board is taken.
I would also suggest using a numerical or a coordinate system to dictate movement.
The board would look like this:
1 2 3
4 5 6
7 8 9
The numbers are corresponding spots on the board.
For example:
In the initialization:
moves = 0
positions = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0, '9':0}
# '1' - '9' are the spots on the board.
# 0 means the spot is empty, 'X' means the spot is taken by 'X', 'O' means the spot is taken by 'O'. You can use any other naming system, but this is simple.
In the movement code:
while 1 == 1: # just a loop until the input is valid. See the 'break' statement below
new_move = input("X, enter what space to move to: ")
if positions[new_move] == 0: # if that board spot is empty
moves += 1 #moves = moves + 1
positions[new_move] == 'X' # board spot is now occupied by 'X'
# code to show the piece on the board
if moves >= 5: # least possible moves to win is 5
win_check(positions)
break
Alternatively, you can use the movement as a function, and have it recursively call itself until the input is valid:
def move_X():
new_move = input("X, enter what space to move to: ")
if positions[new_move] == 0: # if that board spot is empty
moves += 1 #moves = moves + 1
positions[new_move] == 'X' # board spot is now occupied by 'X'
# code to show the piece on the board
if moves >= 5: # least possible moves to win is 5
win_check(positions)
move_O() # this should be defined similarly to 'move_X' except that it would correlate to 'O'.
else:
move_X()
The the win checking method:
def win_check(positions):
if positions['1'] == 'X' and positions['2'] == 'X' and positions['3'] == 'X':
return "Winner: X"
elif # similar things, checking all of the other ways to win.
You need 1 if statement (in the beginning) and 15 elif statements, as there are 8 ways to win for each player, so 16 checks have to be made.

Categories

Resources