We're doing an activity in my Computer Science class, and I'm having trouble understanding what a few lines of code mean.
Here is the initial code (for any background info that you may need).
class SportsMatch(object):
def __init__(self, teamA="Team A", teamB="TeamB"):
self.teamA = teamA
self.scoreA = 0
self.teamAScorePoints = 1
self.teamB = teamB
self.scoreB = 0
self.teamBScorePoints = 1
def setScorePoints(self, teamAScorePoints=1, teamBScorePoints=1):
self.teamAScorePoints = teamAScorePoints
self.teamBScorePoints = teamBScorePoints
def whoWins(self):
if (self.scoreA < self.scoreB):
print(self.teamB+" win the game!")
elif (self.scoreA > self.scoreB):
print(self.teamA+" win the game!")
else:
print("Tie score")
def teamAScores(self):
self.scoreA = self.scoreA + self.teamAScorePoints
def teamBScores(self):
self.scoreB = self.scoreB + self.teamBScorePoints
Then, we're supposed to consider the following code and figure out what each line of code does:
s = SportsMatch("Chargers", "Raiders")
s.setScorePoints(1, 2)
s.teamAScores()
s.teamBScores()
s.teamAScores()
s.teamBScores()
s.whoWins()
I have a sort of general understanding, but my teacher wants us to be more specific. I also understand that the second line is called with the parameters of 1 and 2, but I'm not sure how those numbers play into the rest of the code. If anyone could help explain these last several lines of code to me, it'd be greatly appreciated!
Setting initial variables:
self.teamX = teamX # setting name
self.scoreX = 0 # initial score
self.teamAXcorePoints = 1 # score increment
These two are the score increments:
self.teamAScorePoints = 1
self.teamBScorePoints = 1
Used here to increment each team's score:
def teamAScores(self):
self.scoreA = self.scoreA + self.teamAScorePoints
def teamBScores(self):
self.scoreB = self.scoreB + self.teamBScorePoints
Now the flow:
s = SportsMatch("Chargers", "Raiders") # defining the match
s.setScorePoints(1, 2) # setting initial score increments
s.teamAScores() # team A scores 1 point
s.teamBScores() # team B scores 2 points
s.teamAScores() # team A scores another 1 point
s.teamBScores() # team B scores another 2 points
s.whoWins() # prints winner
A general description of the code:
s = SportsMatch("Chargers", "Raiders")
This line of code calls the __init__ method from the SportsMatch class and passes the method "Chargers" and "Raiders". These are then saved as the names of the sports teams.
s.setScorePoints(1, 2)
This line calls the setScorePoints method from the class and passes it 1 and 2. These values are saved as the amount that each teams scores will be incremented upon scoring.
s.teamAScores()
s.teamBScores()
s.teamAScores()
s.teamBScores()
These lines call the teamAScores and teamBScores methods. These methods increment the scores of a team depending on which method is called.
s.whoWins()
This calls the whoWins method of the class, which compare the teams scores and prints the winning team.
The winning team would be team B also known as Raiders. Team B would have a score of 4 and team A would have a score of 2.
Related
I am trying to create a round-robin tournament with 4 teams. Each team will have a random number generated for goals for and goals against between 0 and 5. The task I am struggling with is creating a final standing sorting table that shows the position of the team, its name, the total number of goals for the team (GF), the total number of goals against the team (GA), and the total number of points. Three points are awarded for a win, one for a draw, and none for a
defeat. The final table should look as follows:
The Final Table (sorted):
Pos Team Name GF GA PTS
1 FC Bayern Munich 11 7 6
2 FC Liverpool 8 7 6
3 Real Madrid 5 7 3
4 Orlando SC 6 9 3
I am not sure how I can calculate the final scores and organize the table so that it puts the team in the correct rank.
Furthermore, how would this code be done if you want to include a number of teams from an input? Any tips to begin that?
Here is what I have so far. Instead of opting for loops, I decided to go the listing route which is now proving to be difficult. I'm not sure how to assign the GF and GA to the team that has those points and then be able to organize those from least to greatest.:
import random
team1 = input("Please enter name of team 1: ")
team2 = input("please enter name of team 2: ")
team3 = input("please enter name of team 3: ")
team4 = input("please enter name of team 4: ")
print()
teams = [team1, team2, team3, team4]
scores = [random.randint(0, 5) for i in range (1,13)]
def schedule():
print("Tournament Results:")
print(team1, "vs.", team2,"", scores[0],":",scores[1])
print(team3, "vs.", team4,"", scores[2],":",scores[3])
print(team1, "vs.", team3,"", scores[4],":",scores[5])
print(team2, "vs.", team4,"", scores[6],":",scores[7])
print(team1, "vs.", team4,"", scores[8],":",scores[9])
print(team2, "vs.", team3,"", scores[10],":",scores[11])
team1GF = scores[0] + scores[4] + scores[8]
team1GA = scores[1] + scores[5] + scores[9]
team2GF = scores[1] + scores[6] + scores[10]
team2GA = scores[0] + scores[7] + scores[11]
team3GF = scores[2] + scores[5] + scores[11]
team3GA = scores[3] + scores[4] + scores[10]
team4GF = scores[3] + scores[7] + scores[9]
team4GA = scores[2] + scores[6] + scores[8]
schedule()
I'm confused what you're asking, you have the goals for and against for each of the teams, do you want help in calculating scores or sorting scores?
If you want a variable amount of teams then it'd be something like this
team_length = int(input("How many teams do you want to play: "))
teams = []
for i in range(team_length):
teams.append(input(f"Please enter the name of team {i+1}: "))
Though for this you'd also need to change the way you're creating scores to something like this
games_length = team_length * team_length-1
scores = [random.randint(0, 5) for i in range(0, games_length)
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.
while this is completely not needed I still want to try and put everything I can in as little lines of code as possible while also using OOP
I have the code done without OOP but someone asked whether it can be done with OOP, the problem can be solved in more lines of code but I want to put as much into just 1 as possible
class Player:
def __init__(self,x,y,z,a):
self.id = x
self.prompt = y
self.score = z
self.overall_scores = a
players = [Player(x,y,random.randint(1,6),{z.id:z.score for z in players}
if x == 3 else None) for x,y in zip(range(0,4),["First", "Second", "Third",
"Fourth"])]
I expect to have each player with their own score and last player to hold the overall scores so that I could sort them by their value to determine the player with the highest score. Note that OOP is not the best way to approach this task but I was asked how it would look with OOP
What the program should do: each player is given a random score and then ranked based on the highest score
Edit:
Since the code without OOP was requested, here it is:
import operator,random
players = {x:0 for x in range(0,4)}
prompts = ["First", "Second", "Third", "Fourth"]
for a in players:
players[a] = random.randint(1,6)
print("%s:\nDice: %s" % (prompts[a],players[a]))
sorted_players = sorted(players.items(),key=operator.itemgetter(1))
draw = True
previous = 0
draw_between = []
first = True
for a in sorted_players[::-1]:
if first:
previous = a[1]
first = False
elif previous != a[1]:
draw = False
if draw:
draw_between.append(a[0])
if draw:
print("The chances of this were astronomically low but it happened anyway!")
print("It's a draw!")
elif len(draw_between) <= 1:
print("%s Player Wins!" % (prompts[sorted_players[-1][0]]))
else:
out = "First place is a draw between Players:\n"
draw_between.sort()
for b,a in enumerate(draw_between):
out += str(prompts[a])
if b < len(draw_between)-1:
out += ", "
print(out)
The comments and the end of the question indicate, you do not need the "overall score" as well as you do not need to collect the score of the last player. If that is the case, then this does what you want, i.e. "each player is given a random score and then ranked based on the highest score" (I assumed you wanted them ranked from first to last):
import random
class Player:
def __init__(self, x, y, z):
self.id = x
self.prompt = y
self.score = z
players = [Player(x,
y,
random.randint(1, 6))
for x, y in zip(range(0, 4), ["First", "Second", "Third", "Fourth"])]
sorted_players = sorted([Player(x,
y,
random.randint(1, 6))
for x, y in zip(range(0, 4), ["First", "Second", "Third", "Fourth"])],
key=lambda dude: dude.score, reverse=True)
I have created a program which simulates an entire football season between teams. The user inputs the teams' names and their skill ratings. It then uses the Poisson distribution to compare their skill ratings and calculate the result between the two teams. After each match, the relevant lists are updated: the winning teams gains 3 points (so if it is the third team that has won then the value at index [2] increases by 3). I have a separate list for points, goals scored, goals conceded, games won, games drawn, and games lost (side note - is there a more efficient way of doing this?)
The problem I have comes at the end of the season: each team is outputted with their data in the order that the teams were originally input. This is done using the fact that a team's name in the 'names' list is the same index as their points in the 'points' list. So the issue is, if I order the 'points' list then they will be out of sync with their names. I hope this makes sense but here is an example output for a season:
Enter number of teams in league: 4
Enter team 1 name: a
Enter team 2 name: b
Enter team 3 name: c
Enter team 4 name: d
Enter a skill: 1
Enter b skill: 3
Enter c skill: 5
Enter d skill: 8
===========================================
a's home games:
===========================================
a 2 - 0 b
a 0 - 2 c
a 0 - 0 d
===========================================
b's home games:
===========================================
b 2 - 3 a
b 1 - 0 c
b 0 - 0 d
===========================================
c's home games:
===========================================
c 1 - 0 a
c 1 - 0 b
c 0 - 1 d
===========================================
d's home games:
===========================================
d 4 - 0 a
d 2 - 0 b
d 0 - 0 c
Final table:
a Skill: 1 Points: 7 For: 5 Against: 9 Goal difference: -4 Wins: 2 Draws: 1 Losses: 3
b Skill: 3 Points: 4 For: 3 Against: 8 Goal difference: -5 Wins: 1 Draws: 1 Losses: 4
c Skill: 5 Points: 10 For: 4 Against: 2 Goal difference: 2 Wins: 3 Draws: 1 Losses: 2
d Skill: 8 Points: 12 For: 7 Against: 0 Goal difference: 7 Wins: 3 Draws: 3 Losses: 0
[4, 7, 10, 12]
So what I would now like to do is to be able to print a final league table in descending points order, rather than the way it prints now just in index order.
Sorry if this is poorly worded - the code for my program might be more useful so here it is:
import math
import random
#Lambda value in Poisson distribution for higher rated team
lambOne = 1.148698355
#Lambda value for lower rated team
lambTwo = 0.8705505633
#Poisson distribution calculating goals scored by the home team
def homeMatch(homeRating,awayRating):
global lambOne
global x
global y
if x == y:
raise ValueError
else:
lamb = lambOne**(int(homeRating)-int(awayRating))
homeScore = 0
z = random.random()
while z > 0:
z = z - ((lamb**homeScore * math.exp(lamb * -1))/(math.factorial(homeScore)))
homeScore += 1
return (homeScore-1)
#Poisson distribution calculating goals scored by away team
def awayMatch(homeRating,awayRating):
global lambTwo
global x
global y
#This check is to stop a team playing itself
if x == y:
raise ValueError
else:
lamb = lambTwo**(int(homeRating)-int(awayRating))
awayScore = 0
z = random.random()
while z > 0:
z = z - ((lamb**awayScore * math.exp(lamb * -1))/(math.factorial(awayScore)))
awayScore += 1
return (awayScore-1)
#Selecting number of teams in league
leagueSize = int(input("Enter number of teams in league: "))
#Initialising empty lists
teamNames = []
teamSkill = []
teamPoints = []
teamFor = []
teamAgainst = []
teamWins = []
teamDraws = []
teamLosses = []
#Populating lists with number of zeroes equal to the number of teams (one zero for each)
for x in range(leagueSize):
teamPoints += [0]
teamFor += [0]
teamAgainst += [0]
teamWins += [0]
teamDraws += [0]
teamLosses += [0]
#Entering names and skill ratings for each team
for i in range(leagueSize):
teamNames += [input("Enter team "+str(i+1)+" name: ")]
for j in range(leagueSize):
teamSkill += [input("Enter "+teamNames[j]+" skill: ")]
#Initialising variables
homeScore = 0
awayScore = 0
#The season begins - each team plays all of its home games in one go
for x in range(leagueSize):
#input("Press enter to continue ")
print("===========================================")
print(teamNames[x]+"'s home games: ")
print("===========================================\n")
for y in range(leagueSize):
error = 0
try:
homeScore = homeMatch(teamSkill[x],teamSkill[y])
#Skipping a game to stop a team playing itself
except ValueError:
pass
error += 1
try:
awayScore = awayMatch(teamSkill[x],teamSkill[y])
except ValueError:
pass
if error == 0:
#Updating lists
print(teamNames[x],homeScore,"-",awayScore,teamNames[y],"\n")
teamFor[x] += homeScore
teamFor[y] += awayScore
teamAgainst[x] += awayScore
teamAgainst[y] += homeScore
if homeScore > awayScore:
teamWins[x] += 1
teamLosses[y] += 1
teamPoints[x] += 3
elif homeScore == awayScore:
teamDraws[x] += 1
teamDraws[y] += 1
teamPoints[x] += 1
teamPoints[y] += 1
else:
teamWins[y] += 1
teamLosses[x] += 1
teamPoints[y] += 3
else:
pass
#Printing table (unsorted)
print("Final table: ")
for x in range(leagueSize):
#Lots of formatting
print(teamNames[x]+(15-len(teamNames[x]))*" "+" Skill: "+str(teamSkill[x])+(5-len(str(teamSkill[x])))*" "+" Points: "+str(teamPoints[x])+(5-len(str(teamPoints[x])))*" "+" For: "+str(teamFor[x])+(5-len(str(teamFor[x])))*" "+" Against: "+str(teamAgainst[x])+(5-len(str(teamPoints[x])))*" "+" Goal difference: "+str(teamFor[x]-teamAgainst[x])+(5-len(str(teamFor[x]-teamAgainst[x])))*" "+" Wins: "+str(teamWins[x])+(5-len(str(teamWins[x])))*" "+" Draws: "+str(teamDraws[x])+(5-len(str(teamDraws[x])))*" "+" Losses: "+str(teamLosses[x])+(5-len(str(teamLosses[x])))*" ")
teamPoints.sort()
print(teamPoints)
Sorry that this is very long and likely poorly worded and inefficient but I hope someone will be able to help me! Thank you very much :)
While your current approach is (barely) workable, it makes it very difficult to (for example) change the information you want to store about each team. You might consider defining a Team class instead, each instance of which stores all the information about a specific team.
class Team:
def __init__(self, name, skill):
self.name = name
self.skill = skill
self.points = self.goals_for = self.goals_against = \
self.wins = self.draws = self.losses = 0
This lets you create a new team object by passing a name and a skill level, in this way:
t1 = Team("Bradford City", 3)
t1 now has attributes name and skill with the given values, as well as a number of others (points, goals_for, and so on) whose values are all zero.
Then you can initialise the league quite easily:
league_size = 4
teams = []
for _ in range(league_size):
teams.append(Team(input("Name of team "+str(_)+": "),
int(input("Team "+str(_)+"'s skill level: ")))
Then to print the skill level of each team you can loop over the list:
for team in teams:
print(team.name, team.skill)
I hope this gives you some idea how your approach can be simplified. Your functions to play the matches can also take teams as arguments now, and modify the team objects directly according to the computed outcomes.
To get to the answer you want, once you have a list of teams you can print them out sorted by the number of points they hold quite easily:
for team in sorted(teams, key=lambda t: t.points):
print(team.name, team.skill, team.points, ...)
As far as I can see, none of your global declarations were necessary (if a name isn't defined locally Python will look for a global name to satisfy a reference). Besides which, inputs to a function should usually be passed as arguments, it's rather bad practice just to grab things from the environment!
I hope this is sufficient for you to rework your program to be more tractable. As a beginner I'd say you have done extremely well to get this far. The next steps are going to be exciting for you!
Added later: Your all-play-all could be easier to program as a result:
for home in teams:
for away in teams:
if home is away: # Teams don't play themselves
continue
play_match(home, away)
The play_match function would simulate the match and adjust each team's statistics. Of course you could simulate the away matches with another line reading
play_match(away, home)
though I'm not sure your algorithm is symmetrical for that.
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