whats wrong with my code to simulate a squash game? - python

I am trying to simulate the scoring of a squash game using english rules.
These are:
Only the server is awarded a point if they win a rally.
If the server wins a rally, they receive a point and continue as server.
If the returner wins a rally, they become the server but don’t receive a point.
The first player to reach 9 points wins the game unless the score has reached 8-8.
If the score reaches 8-8, the player who reached 8 first decides whether to play to 9 or to 10.
The code I have is this:
import random
def eng_game(a,b):
A = 'bob'
B = 'susie'
players = [A, B]
server = random.choice(players)
print server
points_bob = 0
points_susie= 0
prob_A_wins = 0.4
prob_B_wins = 0.6
while points_bob or points_susie < 9:
probability = random.random()
print probability
if probability < prob_A_wins and server == A:
points_bob += 1
elif probability < prob_A_wins and server == B:
server == A
print server
if probability > prob_A_wins and server == B:
points_susie += 1
elif probability > prob_A_wins and server == A:
server == B
print server
print points_bob
print points_susie
This code returns that Susie wins 9-0 when in some cases the server should be swapped to Bob to win the point, but this doesn't happen. The serve stays with Susie and she wins the point.

I think the issue is the statements server == A and server == B should be server = A and server = B so that assignment takes place instead of a comparison.
Another edge case bug I see is if probability ends up exactly 0.4 your program will act like that virtual serve never took place.
I would change your loop to:
while points_bob < 9 and points_susie < 9:
probability = random.random()
print probability
if probability <= prob_A_wins and server == A:
points_bob += 1
elif probability <= prob_A_wins and server == B:
server = A
print server
if probability > prob_A_wins and server == B:
points_susie += 1
elif probability > prob_A_wins and server == A:
server = B
print server
print points_bob
print points_susie

I suspect your loop condition
while points_bob or points_susie < 9:
is not doing what you think. When interpreted as booleans, numbers are False if they are zero and True otherwise, meaning this will actually check (points_bob != 0) or (points_susie < 9). This will only be False (i.e., the loop will only stop) when Susie has at least 9 points and Bob has no points - if Bob gets any points, the game will go on forever.
To fix this, you should switch to an and condition. This will only continue while both players have less than nine points, or to put it another way, it will stop as soon as somebody reaches nine. Therefore, your loop condition should be
while points_bob < 9 and points_susie < 9:
If you want to change the winning condition to 10 points, then you'll need to compare the player's points to a variable rather than a constant, and then change the variable as needed:
winning_score = 9
while points_bob < winning_score and points_susie < winning_score:
# ...
# Accumulate your points etc.
# ...
# Now need to reach ten points to win.
winning_score = 10

Related

Python : Calculating probability of a dice throw function

Hello this is a question I have been tasked with.
..........................................................................................................
You are at the bottom of a staircase with a die. With each throw of the die, you
either move down one step (if you get a 1 or 2 on the dice) or move up one step (if you get a
3, 4, or 5 on the dice). If you throw a 6 on the die, you throw the die again and move up the
staircase by the number you get on that second throw. Note if you are at the base of the
staircase, you cannot move down!
The function has a parameter that takes a probability distribution over all
outcomes from a dice throw. For example (0.2,0.3,0.2,0.1,0.1,0.1) would suggest that the
probability of getting a 1 is 0.2, 2 is 0.3 etc. Calculate the probability of reaching a step
higher than the 200th one for the following case: 100 throws, [0.2,0.2,0.2,0.2,0.1,0.1] distribution.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
I have been able to create some code which serves as the function (I'm sure it could be simplified but I am new to this) however I am unsure as to how to work out the probability of it being higher than the 200th step.
import random
def rolldice(T:int, D): #T = throws, D = distribution in format [0.0,0.0,0.0,0.0,0.0,1] [0.2,0.2,0.2,0.2,0.1,0.1]
Stair = 0
for i in range(T):
print(i,Stair)
roll = random.choices([1,2,3,4,5,6], weights= D)
roll2 = random.choices([1,2,3,4,5,6])
roll1 = roll[0]
if roll[0] == 1 and Stair > 0:
Stair -= 1
elif roll[0] == 2 and Stair > 0:
Stair -= 1
elif roll[0] == 3:
Stair += 1
elif roll[0] == 4:
Stair += 1
elif roll[0] == 5:
Stair += 1
elif roll[0] == 6:
Stair += roll2[0]
return Stair
rolldice(100, [0.2,0.2,0.2,0.2,0.1,0.1])
You could assign T to 1000 by an input function and it would then loop for a certain amount of throws.

My for loop randomly gets stuck and doesnt complete its range

My for loop keeps stopping in main. It is supposed to call the def binarySearch 10000 times and add up the total number of guesses from each try. I notice when I lower the range down to 100, the for loop works MOST of the time. It still sometimes just freezes and never prints anything.
import random
def binarySearch(left, right, x):
counter = 0 #guesses per try
while left <= right:
counter+=1
mid = (right + left) // 2
if x == mid:
return counter
elif x > mid:
left = mid
elif x < mid:
right = mid
def main():
guesses = 0 # total number of guesses
###Problem here###
for x in range(10001):
lef = 0 #min
rig = 1000 #max
num = random.randint(lef, rig) #random number
guesses += binarySearch(lef, rig, num) #calls binarySearch and sums the total guesses
print("Total guesses from 10000 tries: ", guesses)
main()
EDIT:
I narrowed down the problem to:
elif x < mid:
left = mid
I tested it quite a few times and came to the conclusion that the while loop ends up getting stuck repeating that else if statement. I do not know why this is happening though.
The reason it is getting stuck is because there is an error in the boundary condition. If the number is not equal to mid and the left and right should be equal to mid + 1 and mid - 1 respectively. No need to consider mid again. Since you are considering mid again and again, your condition is never coming out of this cycle and hence the infinite loop.
elif x > mid:
left = mid + 1
elif x < mid:
right = mid - 1
These should be your new values for left and right. No need to consider mid again because it is not equal to the target value, if it were, the top most if the condition would have been true.

players roll 2 dice till one reaches 100

Each player roll two dice in a row on one turn. The amount of dice obtained is
added to the player's total points. The game ends when one of the players
the first has achieved at least 100 points.
from random import randint
dicesum2 = 0
dicesum1 = 0
while (dicesum1 < 100):
dice1 = [randint(1, 6) for i in range(2)]
dicesum1 += sum(dice1)
print('player 1',dice1,'|',dicesum1)
dice2 = [randint(1, 6) for i in range(2)]
dicesum2 += sum(dice2)
print('player 2',dice2,'|',dicesum2)
i need it to end when one reaches 100. how do i check both?
if a player throws exactly one single, he loses the points obtained in the turn;
how do i check when one of the generated numbers is 1?
I need it to end when one reaches 100. how do i check both?
Learn about what the or logical operator does:
dicesum1 < 100 or dicesum2 < 100
how do i check when one of the generated numbers is 1?
Learn what the in operator does:
if 1 in dice1:
# Apply penalty.
Take a look at this and see if it helps out
from random import randint
def roll():
return [randint(1, 6) for i in range(2)]
def check_for_one(rolls):
for roll in rolls:
# this could be simplified to "if 1 in rolls", this was just my preference
if roll == 1:
return True
return False
dicesum2 = 0
dicesum1 = 0
while True:
d1 = roll()
dicesum1 += sum(d1)
if check_for_one(d1):
print(f"Player 1 rolled a 1 in batch: {d1}")
print(f"Player 1 roll: {d1} | {dicesum1}")
d2 = roll()
dicesum2 += sum(d2)
if check_for_one(d2):
print(f"Player 2 rolled a 1 in batch: {d2}")
print(f"Player 2 roll: {d2} | {dicesum2}")
if dicesum1 >= 100:
print(f"Player 1 won with: {dicesum1}")
break
elif dicesum2 >= 100:
print(f"Player 2 won with: {dicesum2}")
break
So in this example, we shove the roll out to a function and check_for_one which iterates the list you are making checking for ones and returning a boolean.
I changed the loop to while True so the loop wasn't responsible for the more complex condition which can be limiting.
For each player, it performs the roll, sums, checks and reports if a 1 is in the batch, reports the roll.
Finally it checks for the winner and breaks if one is at or over 100, reporting their win.
You can change the while condition as follow :
while (dicesum1 < 100 and dicesum2 < 100):
Alternatively, you can also use break :
...
if dicesum1 >= 100:
break
...
if dicesum2 >= 100:
break

Monte Carlo simulation of amoeba population

I came across a brain teaser problem. Im trying to simulate it, but having trouble getting the answer. The problem goes like this: there is one amoeba. every minute, an amoeba either may die, stay the same, split into 2 or split into 3 with equal probability. All of its offspring will behave the same way, independent of other amoebas. What is the probability that amoeba population will die?
My implementation in python:
import numpy as np
def simulate(n):
prob = np.array([0.25]*4)
ans = np.random.choice(np.arange(4),1,p=prob)
if ans == 0:
n = n - 1
if ans == 1:
pass
if ans == 2:
n = n * 2
if ans == 3:
n = n*3
return n
count = 0
for i in range(10000):
nold = 1
while True:
nnew = simulate(nold)
if nnew == 0: #amoeba has died
count += 1
break;
nold = nnew
Im getting an infinite loop. Can anybody help? thanks. The answer is 41%
The While loop needs to have some sort of breakpoint.
You have not set what is False.
while count < 10000:
...

python while loop point system - running slow

I have to simulate a points game where the first person to reach 11 points and win by 2 clear points wins the game
I have used a function to decide who wins a point
def simulatePoint(winProbabilityA, winProbabilityB):
rNumber = random.random()
if rNumber - winProbabilityA <= 0:
# A wins the game
return 0
elif rNumber - winProbabilityA > 0:
# B wins the game
return 1
and another one to simulate a game
def simulateGame (playerA_winProb, playerB_winProb):
gameWon = False
pointsA = 0
pointsB = 0
while gameWon == False:
# Simulate point
point = simulatePoint(playerA_winProb, playerB_winProb)
if point == 0:
pointsA += 1
elif point == 1:
pointsB += 1
# Checks for points to be equal to 11
if (pointsA == 11) and (pointsA - pointsB >= 2):
# A wins the game
gameWon = True
return 0
elif (pointsB == 11) and (pointsB - pointsA >= 2):
# B wins the game
gameWon = True
return 1
This is where i believe i am going wrong, i think the while loop is causing the code to run slow
Any help is greatfully accepted
What if the difference becomes greater than or equal to 2, after they have won more than 11 games. So, the logic should have been like this
if (pointsA >= 11) and (pointsA - pointsB >= 2):
...
elif (pointsB >= 11) and (pointsB - pointsA >= 2):
...
I think your code is running infinitely.
Consider: pointsA and pointsB reach 10 and 10 respectively. Now, no matter what player gets the next point, neither of your terminating conditions will be reached because neither pointsA nor pointsB will be 11 and up by 2 at the same time. This creates an infinite loop.
You'd probably want to check if pointsA >= 11 and pointsB >= 11 instead of A == 11 and B == 11.
Looks like thefourtheye beat me by a bit - he gets my vote.

Categories

Resources