How would you go about making this loop? - python

A standard science experiment is to drop a ball and see how high it bounces. Once the “bounciness” of the ball has been determined, the ratio gives a bounciness index. For example, if a ball dropped from a height of 10 meters bounces 6 meters high, the index is 0.6 and the total distance traveled by the ball is 16 meters after one bounce. If the ball were to continue bouncing, the distance after two bounces would be 10 meters + 6 meters + 6 meters + 3.6 meters = 25.6 meters. Note that distance traveled for each successive bounce is the distance to the floor plus 0.6 of that distance as the ball comes back up.
Write a program that lets the user enter the initial height of the ball and the number of times the ball is allowed to continue bouncing. Output should be the total distance traveled by the ball.
What I have so far is :
def Bounce_Calculator():
initialHeight = float(input( "What is the initial height? "))
bouncesAllowed = float(input( "What is the amount of bounces allowed: "))
bounceIndex = float(input("What is the bounce index : "))
n=0
while n <= bouncesAllowed :
newHeight = float(initialHeight*bounceIndex)
heightDifference = initialHeight-newHeight
bounceSum = (newHeight/1-bounceIndex)
totalDistance = ((((2*bounceSum) + initialHeight )))
print ("The total distance is : ", totalDistance)
n=bouncesAllowed + 1
Bounce_Calculator()

This is a classic recursion process.
There are three approaches that one might take:
recursive method. (needs end condition)
while loop. (needs end condition)
for loop. (finishes at the end of the loop)
Using method 3 from the above this works:
def Bounce_Calculator(initial_height:float, bouncyness:float,
len_travelled=0):
''' takes height and bouncyness and returns then next bounce
'''
next_bounce = initial_height * bouncyness
len_travelled += initial_height + bouncyness
return next_bounce, len_travelled
# initial conditions
len_trav = 0
list_of_cycles = [0]
h = 100
b = 0.6
# the loop
for i in range(1, 10):
h, len_trav = Bounce_Calculator(h, b, len_trav)
list_of_cycles.append(len_trav)
percent_moved = (list_of_cycles[i]-list_of_cycles[i-1]) / list_of_cycles[i]
if percent_moved < 0.01:
# stopped bouncing
break
print('bounces', list_of_cycles)
print('total length travelled', len_trav)
result:
bounces [0, 100.6, 161.2, 197.79999999999998, 219.99999999999997, 233.55999999999997, 241.93599999999998, 247.20159999999998, 250.60096, 252.880576]
total length travelled 252.880576

Related

Risk game with python

i am pretty much starting to learn code so my knowledge is limited.
following scenario:
there is this "risk" game where playerA rolls a dice three times and playerB two times. now the two highest results of playerA are compared to the two of player B. if the highest result of A is greater than playerBs, player A gets a point, otherwise (<=) B gets a point. The same for the second highest result of A and B. So the total results of the points could be: 2:0, 1:1 or 0:2
Now the question:
The are obviously 6^5=7776 ways to dice and 2890 of them lead to 2:0, 2611 to 1:1 and 2275 to 0:2.
How can i show this statistic by printing out for example "There are 2890 possibilities to win 2:0" ?
I am able to show for a random dice roll who wins the game, but not for all.
I would be very thankful for some help.
import random
r1 = random.randint(1,6)
r2 = random.randint(1,6)
r3 = random.randint(1,6)
b1 = random.randint(1,6)
b2 = random.randint(1,6)
Points_A = 0
Points_B = 0
Dice_A = [r1,r2,r3]
Dice_B = [b1,b2]
print("results of A: ", Dice_A)
print("results of B: ", Dice_B)
A = sorted(Würfel_A)
B = sorted(Würfel_B)
if A[2] > B[1]:
Points_A += 1
elif A[2] == B[1]:
Points_B +=1
else: Points_B += 1
if A[1] > B[0]:
Points_A += 1
elif A[1] == B[0]:
Points_B += 1
else: Points_B += 1
print("A has ", Points_A, "Points.")
print("B has ", Points_B, "Pionts.")
Here is how I would do it:
Create a function that casts a given number of dice and sorts the results in descending order, and returns that list. For example cast_dice(3) could return [6, 4, 1]
Use that function to produce a result for the red player and the blue player. Then zip those two lists (the third die of the red player will not play a role) so the mutual dice can be compared. Calculate the number of dice with which red wins. Red can win with either 0, 1 or 2 dice.
To get statistics on distribution, you could create a list with three counters: one for each possible red-score. Run the above procedure thousands of times and to populate this list of three.
Calculate an average score from that list of three
Here is an implementation:
from random import randint
def cast_dice(dice_count):
return sorted((randint(1, 6) for _ in range(dice_count)), reverse=True)
def get_stats(num_rounds):
score_counts = [0, 0, 0] # red can score 0, 1 or 2 per round
for round in range(num_rounds):
reds = cast_dice(3)
blues = cast_dice(2)
score = sum(int(red > blue) for red, blue in zip(reds, blues))
score_counts[score] += 1
return score_counts
score_counts = get_stats(10000)
red_wins = score_counts[1] + 2 * score_counts[2]
blue_wins = score_counts[1] + 2 * score_counts[0]
avg_score = red_wins / sum(score_counts)
print("Raw score counts: ", score_counts)
print("Number of winning red dice: ", red_wins)
print("Number of winning blue dice: ", blue_wins)
print("Average score for red per round: ", avg_score) # ~1.08...
print("Average score for blue per round: ", 2 - avg_score) # ~0.92...
print("For every blue winning die, red has", red_wins / blue_wins, "winning dice")
So this sampling suggests that the expected outcome per round is that red wins one, and blue wins one, but that red has a tiny advantage: it will happen a bit more often that red wins two than that blue wins two.
This corresponds to the mathematical results you provided in the question.
To put it a bit differently, after 13 rounds (of 3 dice against 2), blue will have lost 2 "armies" more than red (on average).

Python Ray Collisions Logic Incorrect (USACO 2020 December Bronze Q3 "Stuck in a Rut")

I am trying to solve this question from the USACO website. Problem Link: http://www.usaco.org/index.php?page=viewproblem2&cpid=1061
Farmer John has recently expanded the size of his farm, so from the perspective of his cows it is effectively now infinite in size! The cows think of the grazing area of the farm as an infinite 2D grid of square "cells", each filled with delicious grass (think of each cell as a square in an infinite chessboard). Each of Farmer John's N cows (1≤N≤50) starts out in a different cell; some start facing north, and some start facing east.
Every hour, every cow either
Stops if the grass in her current cell was already eaten by another
cow.
Eats all the grass in her current cell and moves one cell forward
according to the direction she faces.
Over time, each cow therefore leaves a barren "rut" of empty cells behind her.
If two cows move onto the same grassy cell in the same move, they share the cell and continue moving in their respective directions in the next hour.
Please determine the amount of grass eaten by each cow. Some cows never stop, and therefore eat an infinite amount of grass.
INPUT FORMAT (input arrives from the terminal / stdin):
The first line of input contains N. Each of the next N lines describes the starting location of a cow, in terms of a character that is either N (for north-facing) or E (for east-facing) and two nonnegative integers x and y (0≤x≤1000000000, 0≤y≤1000000000) giving the coordinates of a cell. All x-coordinates are distinct from each-other, and similarly for the y-coordinates.
To be as clear as possible regarding directions and coordinates, if a cow is in cell (x,y) and moves north, she ends up in cell (x,y+1). If she instead had moved east, she would end up in cell (x+1,y).
OUTPUT FORMAT (print output to the terminal / stdout):
Print N lines of output. Line i in the output should describe the number of cells worth of grass that the ith cow in the input eats. If a cow eats an infinite amount of grass, output "Infinity" for that cow.
SAMPLE INPUT:
6
E 3 5
N 5 3
E 4 6
E 10 4
N 11 2
N 8 1
SAMPLE OUTPUT:
5
3
Infinity
Infinity
2
5
SCORING:
In test cases 2-5, all coordinates are at most 100.
In test cases 6-10, there are no additional constraints.
My logic is that since simulating the collisions would be too slow because the field is huge, we can sort the cows by their x values, iterate over all the collisions/intersections of cows and stop the ones that should be stopped, and after iterating, print out the distances of the stopped cows. And if a cow hasn't stopped, print "Infinity".
My code:
# Defining the cow class with the original order position, x, y, distance,
# and whether or not it stopped.
class Cow:
def __init__(self, i, x, y):
self.i = i
self.x = x
self.y = y
self.dist = 0
self.stopped = False
# Get input from console and split cows into east facing and north facing cows.
n = int(input().strip())
hor = []
ver = []
ans = [0] * n
for i in range(n):
line = input().strip().split()
if line[0] == 'E':
hor.append(Cow(i, int(line[1]), int(line[2])))
else:
ver.append(Cow(i, int(line[1]), int(line[2])))
hor.sort(key = lambda c: c.x)
ver.sort(key = lambda c: c.x)
# Iterate over every possible collision. Logic problem here:
for h in hor:
for v in ver:
vdist = abs(h.y - v.y)
hdist = abs(h.x - v.x)
if h.stopped and v.stopped:
continue
elif h.stopped:
if v.x >= h.x and v.x <= h.x + h.dist and v.y <= h.y:
if vdist > hdist:
v.dist = vdist
v.stopped = True
elif v.stopped:
if v.x >= h.x and h.y <= v.y + v.dist and v.y <= h.y:
if hdist > vdist:
h.dist = hdist
h.stopped = True
else:
if v.x >= h.x and v.y <= h.y:
if vdist > hdist:
v.dist = vdist
v.stopped = True
if hdist > vdist:
h.dist = hdist
h.stopped = True
# Combine the lists and put them back into the original order.
cows = hor + ver
cows.sort(key = lambda c: c.i)
# Print out all the cows' distances, and it a cow hasn't stopped, replace distance with Infinity.
for i in cows:
if not i.stopped:
i.dist = "Infinity"
print(i.dist)
I'm not sure if it's just my code that isn't correct, or if it's my basic logic. If anyone can provide a fix, it would be appreciated.
Try this revised approach, using set to add the movements and check intersection.
from collections import deque
import sys
class Cow:
def __init__(self, d, x, y, amt):
self.d = d
self.x = x
self.y = y
self.amt = amt
lines = sys.stdin.read().strip().split('\n')
n = int(lines[0])
EMPTY = set()
COW = []
for line in lines[1:]:
d, x, y = line.split()
x, y = int(x), int(y)
COW.append(Cow(d, x, y, 0))
S = set()
for i in range(n):
for j in range(n):
S.add(abs(COW[i].x - COW[j].x))
S.add(abs(COW[i].y - COW[j].y))
S2 = set()
for k in S:
S2.add(k -1)
S2.add(k)
S2.add(k + 1)
S2.add(max(S) + 1)
dq = deque(sorted(S2)) #
SCORE = [None for _ in range(n)]
t = 0
while dq:
#nt += 1
dt = dq.popleft() - t
dt = max(dt, 1)
t += dt
VOID = []
for i in range(n):
if SCORE[i] is None:
if (COW[i].x, COW[i].y) in EMPTY:
SCORE[i] = COW[i].amt
continue
VOID.append((COW[i].x, COW[i].y))
if COW[i].d == 'N': COW[i].y += dt
elif COW[i].d == 'E': COW[i].x += dt
COW[i].amt += dt
for spot in VOID: EMPTY.add(spot)
for i in range(n):
print(SCORE[i] if SCORE[i] else 'Infinity')
To keep track of your algorithm you could split 'intersection-finding' and 'cow-stopping' into separate parts.
import sys
from collections import namedtuple
Cow = namedtuple('Cow', ['distance','facing','x','y','number'])
lines = sys.stdin.read().strip().split('\n')
cows = [Cow(0,*[int(x) if x.isnumeric() else x for x in i.split()], e)
for e,i in enumerate(lines[1:])]
# finding intersections
# save if distances differ, sorted descending by distance
intersections = []
for cowA, cowB in [(cowA, cowB)
for cowB in cows if cowB.facing == 'N'
for cowA in cows if cowA.facing == 'E'
]:
if cowA.x < cowB.x and cowA.y > cowB.y:
d1, d2 = cowB.x - cowA.x, cowA.y - cowB.y
if d1 != d2:
intersections.append(
sorted([Cow(d1, *cowA[1:]),Cow(d2, *cowB[1:])], reverse=True))
# sorting intersections by larger distance
# checking if a cow reached the intersection or stopped earlier
distances = [int(10E9)] * len(cows)
for i in sorted(intersections):
if i[1].distance < distances[i[1].number] and i[0].distance < distances[i[0].number]:
distances[i[0].number] = i[0].distance
for i in distances:
print('Infinity' if i==int(10E9) else i)
Output
5
3
Infinity
Infinity
2
5
My mistake was hor.sort(key = lambda c: c.x) where I sorted the list by the 1st element instead of the 2nd.
It should be hor.sort(key = lambda c: c.y) since that's what matters at the intersections.

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.

Generating moves in Othello with bitboards

I have made two very similar Othello AIs. In the first one, the board is represented as an array of length 100 (10x10) where the 8x8 board is represented in the "middle" of the array and the rest of the array is buffer spaces around the edge (index 11 is top left corner of 8x8 board, index 88 is bottom right corner). To make a move at position index, I use the following code:
changed = [index]
for direction in (1, 9, 10, 11):
shift = index - direction
while board[shift] == opp:
shift -= direction
if board[shift] == player:
changed += [*range(shift + direction, index, direction)]
for direction in (1, 9, 10, 11):
shift = index + direction
while board[shift] == opp:
shift += direction
if board[shift] == player:
changed += [*range(index + direction, shift, direction)]
To generate moves, I then go through the possible indices (which are tiles in the inner 8x8 board) and check if len(changed) > 1. If it is, I set the tiles of the board in changed to that player.
In the second AI, which I had expected would be faster in making moves, the board is represented as two 64-bit bitboards - one for the player aiming to maximize the score and another for the player trying to minimize the score. To make a move, I use the same code as here just converted into Python:
new_disk = 1 << index
captured = 0
newmy_disks = my_disks | new_disk
for direction in range(8):
x = shift(new_disk, direction) & opp_disks
for i in range(5):
x |= shift(x, direction) & opp_disks
bounding_disk = shift(x, direction) & my_disks
if bounding_disk != 0:
captured_disks |= x
newmy_disks = newmy_disks ^ captured_disks
newopp_disks = opp_disks ^ captured_disks
With the bitboard representation, playing 1000 random games takes around 7 seconds, while the array representation takes 4 seconds.
How can I make the bitboard representation faster in generating and making moves, and would it be possible to check possible moves and return the new bitboards at the same time?

Loop Table using distance = speed * time

The distance a vehicle travels can be calculated as follows:
distance = speed * time
Write a program that asks the user for the speed of a vehicle (in miles per hour) and how many hours it has traveled. The program should then use a loop to display the distance the vehicle has traveled for each hour of that time period. Here is an example of the output:
What is the speed of the vehicle in mph? 40
How many hours has it traveled? 3
Hour Distance Traveled
1 : 40
2 : 80
3 : 120
I've gotten everything done so far but can't manage to get the table to come out properly, as shown in the example table at the first hour (1) it should start at 40 but instead it starts at 120. Can someone help me fix the code? forgot to mention it should work for any value the user enters such as if someone was going 50 mph in 5 hours
g = 'y'
while g == 'Y' or g == 'y':
speed = int(input('Enter mph: '))
time = int(input('Enter hours: '))
if time <= 0 or speed <= 0:
print('Invalid Hours and mph must be greater than 0')
else:
for t in range(time):
distance = speed * time
print(t + 1,':', distance)
time = time * 2
g = 'n'
print('End')
Just change 2 things in your program. First, there's no need to double the time inside for loop, Second use variable t instead of time to calculate distance.
g = 'y'
while g == 'Y' or g == 'y':
speed = int(input('Enter mph: '))
time = int(input('Enter hours: '))
if time <= 0 or speed <= 0:
print('Invalid Hours and mph must be greater than 0')
else:
for t in range(time):
distance = speed * (t+1) // Use t+1 instead of time
print(t + 1,':', distance)
# time = time * 2 // No need to double the time
g = 'n'
print('End')
Input:
40
3
Output:
(1, ':', 40)
(2, ':', 80)
(3, ':', 120)
End
You need to remove the commas from the print line, and print out the numbers in string format and concat it to the string colon like:
print(str(t + 1) + ':' + str(distance))
You also need to increment the time by one not multiply by 2
time = time + 1
Your output distance also can be fixed by calculating it based on t instead of time
distance = speed * (t+1)

Categories

Resources