Making a statistics program - python

I am trying to write a Python program that computes and prints the following :
the average score from a list of scores
the highest score from a list of scores
the name of the student who got the highest score.
The program starts by asking the user to enter the number of cases. For EACH case, the program should ask the user to enter the number of students. For each student the program asks the user to enter the student's name and marks. For EACH case the program reports the average marks, the highest marks and the name of the student who got the highest marks.
Also
If there are more than one person with the highest score in a CASE, the program should report the first occurrence only.
The average score and the highest score should have exactly 2 decimal places.
The output should be as in the sample program output.
What I have been trying so far is the following:
grade=[]
name_list=[]
cases=int(input('Enter number of cases: '))
for case in range(1,cases+1):
print('case',case)
number=int(input('Enter number of students: '))
for number in range (1,number+1):
name=str(input('Enter name of student: '))
name_list.append(name)
mark=float(input('Enter mark of student:'))
grade.append(mark)
highest= max (grade)
average=(sum(grade)/number)
high_name=grade.index(max(grade))
print('average',average)
print('Highest',highest)
print (high_name)
This is what i have deciphered so far. my biggest problem now is getting the name of the individual with the high score. Any thoughts and feedback is much appreciated. As with respect to the answer posted below, i am afraid the only thing i do not understand is the dictionary function but otherwise the rest does make sense to me.

This resembles an assignment, it is too specific on details.
Anyways, the official docs are a great place to get started learning Python.
They are quite legible and there's a whole bunch of helpful information, e.g.
range(start, end): If the start argument is omitted, it defaults to0
The section about lists should give you a head start.

numcases = int(input("How many cases are there? "))
cases = list()
for _ in range(numcases):
# the _ is used to signify we don't care about the number we're on
# and range(3) == [0,1,2] so we'll get the same number of items we put in
case = dict() # instantiate a dict
for _ in range(int(input("How many students in this case? "))):
# same as we did before, but skipping one step
name = input("Student name: ")
score = input("Student score: ")
case[name] = score # tie the score to the name
# at this point in execution, all data for this case should be
# saved as keys in the dictionary `case`, so...
cases.append(case) # we tack that into our list of cases!
# once we get here, we've done that for EVERY case, so now `cases` is
# a list of every case we have.
for case in cases:
max_score = 0
max_score_student = None # we WILL need this later
total_score = 0 # we don't actually need this, but it's easier to explain
num_entries = 0 # we don't actually need this, but it's easier to explain
for student in case:
score = case[student]
if score > max_score:
max_score = score
max_score_student = student
total_score += score
num_entries += 1
# again, we don't need these, but it helps to demonstrate!!
# when we leave this for loop, we'll know the max score and its student
# we'll also have the total saved in `total_score` and the length in `num_entries`
# so now we need to do.....
average = total_score/max_entries
# then to print we use string formatting
print("The highest score was {max_score} recorded by {max_score_student}".format(
max_score=max_score, max_score_student=max_score_student))
print("The average score is: {average}".format(average=average))

Related

Problems with random "Lists"

I want to create a game where a person is drawn out randomly.
Can some1 check the code if everything is setup correctly.
I have tested the code numerous times and its ok in my eyes.
But when I send the code to a review, to an online class I only get 50% score.
import random
# 🚨 Don't change the code below 👇
test_seed = int(input("Create a seed number: "))
random.seed(test_seed)
# Split string method
names_string = input("Give me everybody's names, separated by a comma. ")
names = names_string.split(", ")
# 🚨 Don't change the code above 👆
#Write your code below this line 👇
print(names)
names_count = len(names)
random_name_number = random.randint(0, names_count)
print(f"{names[random_name_number]} is going to buy the meal today!")
The problem here is almost certainly with randint. Unlike most Python conventions, the parameters to randint are inclusive. That means, if you supply (0,10), you are going to get numbers from 0 to 10. In your case, if they supply 10 names, using index 10 is going to cause an exception.
You want random.randrange, not random.randint. randrange(0,10) will supply numbers from 0 to 9.

How do I add numbers I've iterated into a list to a string?

I've got a tiny project I'm working on: I'm trying to make a "grading" program that lets you enter the number of exams, the scores for each exam, and then prints the results.
What I'm looking to do:
Enter the number of tests:
use that number with the string "Exam #: " to number each test.
I've gotten as far as sticking the input from "Enter the number of tests:" into a list..(looks like [0,1,2,3,4.. etc] now I'm trying to combine each of those list numbers with the above string and nothing I'm trying is working.. suggestions?
This is what I came up with, and its output:
test1 = int(input('How many tests are there? '))
test2 = []
for number in range(test1):
test2.append(number)
for number2 in test2:
print('Exam #:' + str(number2))
(inputting "5" here)
Exam #:0
Exam #:1
Exam #:2
Exam #:3
Exam #:4
exactly what I needed!
Try something link this
num_exams = int(input('Enter the number of exams: '))
exam_scores = [int(input(f'Enter score for exam #{n+1}: ')) for n in range(num_exams)]
print(f'Average score: {sum(exam_scores) / num_exams:0.2f}')
Seems like you'd want to collect inputs for the number of tests and then all the test scores. Then to print the test scores you could do something like
for test in range(numTests):
print('Exam #' + (test+1) + ': ' + testScores[test])
The (test+1) is so that you could have the same variable manage the test number as well as the index in the test array. For example, it could print
Exam #1: 82
Exam #2: 93
Exam #3: 87
Not sure if this is needed for your program, but you can iterate through all your values in a list with a for loop. This allows you you to access each value and perform some set of commands on that value. So in this example, we will access each value and then print it. Print can take multiple arguments. It will print out each argument with a space in between.
for examNumber in myList:
print ('Exam', examNumber)

Python Input Validation with multiple variables...simplified?

First, I've searched this site, a lot, and found other posts about this topic, even the same assignment I'm working on, so the code is very similar... However, there are a few things slightly different. I'm taking this course, using "Starting out with Python, 4th edition," and my assignment is from chapter 5, "15. Test Average and Grade." I've got the code written for everything except input validation, which my instructor insists we use, though we are only supposed to use coding techniques the book has covered up to this point: no lists, tuples, dictionaries, lambda, etc... Which makes most of the examples I've found online (and on this site) for input validation useless, as I can't figure them out and couldn't use them if I wanted to. I've reached out to the instructor for help (online course), but haven't received any reply for weeks, so I'm here. The program is supposed to ask the user to input 5 test scores, find the average of the scores, assign a letter grade to each score, then display the scores w/ letter grade as well as the average. I thought it'd be easier to validate the input if I asked for the scores with a "for scores in range(1, 6)" loop, but then I don't know how to access each score input by the user to send to the determine_grade function and later to display in main (I didn't include any of that code below)... So I ended up making a variable for each score, but then I run into the problem of how to validate the input (make sure the score entered isn't less than 0 or greater than 100, or that the user has entered a number and not a letter) for each variable. I'd like to be able to write some exception handling into the code so that if the user has entered a letter instead of a number an exception isn't thrown, because my instructor has said "it's my job from now on to try to crash your program," though he hasn't gotten back to me on exactly how to implement this kind of input validation. Any help at all would be greatly appreciated, I've been struggling with this for days now, and it's seriously stressing me out.
EDIT: TypeError: input_validation() missing 4 required positional arguments: 'score2', 'score3', 'score4', and 'score5' is the error I'm getting, I know I'm doing something wrong, however, I don't know what... I feel like there is an easier way to handle input validation for multiple variables.. Since I'm still quite new at this, I've no idea whatsoever how to implement it though.
def get_scores():
score1 = input_validation(float(input('Enter the score for the first test: ')))
score2 = input_validation(float(input('Enter the score for the second test: ')))
score3 = input_validation(float(input('Enter the score for the third test: ')))
score4 = input_validation(float(input('Enter the score for the fourth test: ')))
score5 = input_validation(float(input('Enter the score for the fifth test: ')))
return score1, score2, score3, score4, score5
def input_validation(score1, score2, score3, score4, score5):
while (score1, score2, score3, score4, score5) < 0 or (score1, score2, score3, score4, score5) > 100:
print('Score cannot be less than 0 or greater than 100!')
(score1, score2, score3, score4, score5) = float(input('Please enter a correct test score: '))
return score1, score2, score3, score4, score5
Your immediate error is that you've defined input_validation() to take five parameters, but you're only passing it one parameter when you call it.
It's awkward to collect input in one function and validate the input in another function, because those functions would have to be very tightly coordinated to allow for reprompting on bad input.
It's also awkward to ask for several scores at once and then validate them all at once, because what do you do if some scores are valid and some aren't? You have to either ask for all the scores again, which wastes the user's time, or you need a way of reprompting only for the invalid scores, which is needless complexity.
It might be a better design to handle just one score at a time, with all the input and validation in one place:
def input_validation(prompt):
# keep looping until they enter a good score
while True:
# get the answer as a string
answer = input(prompt)
try:
# convert to float
score = float(answer)
# if in range, we're done! return the converted score number
if 0 <= score <= 100:
return score
# otherwise out of range, print an error message and keep looping
else:
print('Score cannot be less than 0 or greater than 100!')
# if the answer wasn't a number, print an error message and keep looping
except ValueError:
print ('That is not a test score.')
Then you can call it like this:
score1 = input_validation('Enter the score for the first test: ')
score2 = input_validation('Enter the score for the second test: ')
If you want to keep the scores in a list instead of having five separate variables:
scores = []
for i in range(5):
scores.append(input_validation('Enter the score for test number %d: ' % i+1))

Dictionary not updating if key and value are not unique

Im new to python and Im creating this gambling game where a user will have the choice to bet on symbols that will be generated (eventually- haven't gotten there yet). Im creating a dictionary to hold my data for how much the user is betting (the value) and the number corresponding to the symbol they are betting on (the key). Each player has the option to place more than 1 bet per turn. I am running into a problem where if two different players input the same bet&symbol combination (for example $10 on 1 (Crown)) then the dictionary wont update to contain 2 separate entries of 1:10, it will only have one entry of 1:10. This is what Im working with right now
def getPlayers():
print("Hello and Welcome to the Crown and Anchor Game")
num = int(input('Please enter the number of people playing today: ')) # takes the number of people who are playing from the user
scoreInit = [] # creating an empty list for the players inital score of 10
for i in range(num): # for loop to append the inital score of 10 to the empty list scoerInit for the amount of players input
scoreInit += i * [10]
return scoreInit # returns the list of inital scores for the amount of players playing
def collectBets(balance):
bets = {}
index = 0
for i in balance:
index += 1
print('Player %d, what would you like to do this round?' % (index))
print('1: Bet on a symbol')
print('2: Skip this round')
userOpt = int(input('Please enter 1 or 2 depending on your choice: ')) # assigning what the user inputs as the variable 'usesrOpt'
if userOpt == 1: # if user decides to bet:
betTimes = int(input('How many times would you like to bet this round?: '))
for a in range(betTimes):
betAmount = int(input('Enter the amount you would like to bet this round: $1, $2, $5, or $10: '))
symbol = int(input('Enter the number corresponding to the symbol you would like to bet on\n' # asking user what symbol they want to bet on - assigning it to a variable
'1: Crown\n'
'2: Anchor\n'
'3: Heart\n'
'4: Diamond\n'
'5: Club\n'
'6: Spade\n'
))
bets.update({symbol:betAmount})
print(bets)
def main():
balance1 = getPlayers()
collectBets(balance1)
main()
Any help would be much appreciated! Thank you!
It is best to think of a Python Dictionary as "an un ordered set of key: value pairs, with the requirement that the keys are unique (within one dictionary)." https://docs.python.org/3/tutorial/datastructures.html
With that being said, whenever user A chooses 10, and then user B chooses 10; user A choice is literally being overwritten by user B's choice. A single dictionary can only hold 10 once as a key. In order to resolve your solution you'll have to use some other data structures. The key within a dictionary should be unique.
A solution to your problem could be to use different levels of dictionaries. You could have a dictionary of player names that holds a dictionary of their value, and their symbol. However, your player names would have to be unique, otherwise you would run into the same issue.

Dictionary Manupilation

We represent scores of batsmen across a sequence of matches in a two level dictionary as follows:
{'match1':{'player1':57, 'player2':38}, 'match2':{'player3':9, 'player1':42}, 'match3':{'player2':41, 'player4':63, 'player3':91}
Each match is identified by a string, as is each player. The scores are all integers. The names associated with the matches are not fixed (here they are 'match1','match2','match3'), nor are the names of the players. A player need not have a score recorded in all matches
Define a Python function "orangecap(d)" that reads a dictionary d of this form and identifies the player with the highest total score. Your function should return a pair (playername,topscore) where playername is a string, the name of the player with the highest score, and topscore is an integer, the total score of playername.
The input will be such that there are never any ties for highest total score.
For instance:
orangecap({'match1':{'player1':57, 'player2':38}, 'match2':{'player3':9, 'player1':42}, 'match3':{'player2':41, 'player4':63, 'player3':91}})
('player3', 100)
orangecap({'test1':{'Ashwin':84, 'Kohli':120}, 'test2':{'ashwin':59, 'Pujara':42}})
('Kohli', 120)
This is my code:
def orangecap(d):
s=[]
t=[]
for i in sorted(d.keys()):
for j in sorted(d[i].keys()):
flag=0
for k in range(len(s)):
if(s[k]==j):
t[k:k]+=[d[i][j]]
flag=1
break
if(flag==0):
s.append(j)
t.append(d[i][j])
m=max(t)
for i in range(len(t)):
if t[i]==m:
return (s[i],m)
You didn't quite get a question out there, in future try be specific in what you are asking or try https://codereview.stackexchange.com/ for general pointers etc.
First to note in python, as in all programming languages try to be as expressive as possible when naming variables, it will make it much easier for everyone (most often yourself) to work out what is going on (and wrong).
So in the question we are trying to work out the total scores for each player. In other words we are combining the dictionary for each match into a single dictionary, adding if we have a duplicate key. So
def orangecap(d):
# Make a new dict to count the totals
totals = {}
# Loop over every players score in every match.
for match in d.values():
for player in match:
# Check if player is in totals dictionary. If not add them.
if player not in totals:
totals[player] = 0
# Add players score in this match to there total score.
totals[player] += match[player]
#initialise highest_total as we will use it later for comparison.
highest_total = -1
#loop through totals to find highest score
for player in totals:
# if players score is greater than current highest, set highest_player
# to be current player, and set the highest total to players total
if totals[player] > highest_total:
highest_player = player
highest_total = totals[player]
# return the highest player and highest total
return highest_player, highest_total

Categories

Resources