The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.
|
 |
|
Dev Shed Forums
> Programming Languages
> Python Programming
|
Could anyone help me on a Python programming assignment?
Discuss Could anyone help me on a Python programming assignment? in the Python Programming forum on Dev Shed. Could anyone help me on a Python programming assignment? Python Programming forum discussing coding techniques, tips and tricks, and Zope related information. Python was designed from the ground up to be a completely object-oriented programming language.
|
|
 |
|
|
|
|

Dev Shed Forums Sponsor:
|
|
|

November 4th, 2012, 04:32 PM
|
|
Registered User
|
|
Join Date: Nov 2012
Posts: 16
Time spent in forums: 2 h 41 m 15 sec
Reputation Power: 0
|
|
|
Could anyone help me on a Python programming assignment?
Hello, I have been working on an assignment and Iv gotten stuck and can't figure out what to fix.
The assignment:
Write a program that will read an unknown number of bowlers and their bowling scores (with possible values from 1 to 300) from an external file called "bowlingscores.txt". The file will look similar to the following:
David
102
Hector
300
Mary
195
Jane
160
Sam
210
Output the bowlers’ names to an external data file called "bowlingaverages.txt". Next to each bowler's name, print a message dependent on their scores:
For perfect scores (equal to 300), output “perfect”
For those scores greater than the average score, output “above average”
For those below average, output “below average”
Your program must include at least one function (e.g., to calculate the average, to determine the appropriate message to print, etc.).
Here is what I have so far:
Code:
def bowling_scores(filename):
infile = open(filename, "r")
bowling_info = []
count = 0
for line in infile:
parts = line.split("/n")
count += 1
if count == 1 or count % 2 == 1:
info["name"] = parts[0]
if count % 2 == 0:
info["score"] = int(parts[0])
bowling_info.append(info)
infile.close()
return bowling_info
def bowling_avg(filename):
outfile = open(filename, "r")
bowling_avg = []
for key in sorted(bowling_info):
score = bowling_info["score"]
avg_score = (sum(score) / len(score))
avg = ""
if score == 300:
avg = "perfect"
bowling_avg.append(avg)
elif score > avg_score:
avg = "above average"
bowling_avg.append(avg)
elif score < avg_score:
avg = "below average"
bowling_avg.append(avg)
outfile.close()
return bowling_avg
outfile = open("bowling_avg.txt", "w")
for key in sorted(bowling_avg):
outfile.write("%s %s\n" % (bowling_info[name], avg))
|

November 4th, 2012, 05:50 PM
|
 |
Contributing User
|
|
|
|
I'll modify your first function to return a list of dictionaries.
Code:
def bowling_scores(filename):
infile = open(filename, "r")
bowling_info = []
count = 0
for line in infile:
parts = line.split("\n")
count += 1
if count == 1 or count % 2 == 1:
info = dict(name=parts[0]) ########## make a new dictionary
if count % 2 == 0:
info["score"] = int(parts[0])
bowling_info.append(info) ####### indent this line!
infile.close()
return bowling_info
I have a file named bs with your sample data.
I call your function, and display the result, and I suggest you use this list of dictionaries as the input argument to the other function. Looks like this:
Code:
>>> bi = bowling_scores('bs')
>>> import pprint
>>> pprint.pprint(bi)
{'name': 'David', 'score': 102},
{'name': 'Hector', 'score': 300},
{'name': 'Mary', 'score': 195},
{'name': 'Jane', 'score': 160},
{'name': 'Sam', 'score': 210}]
>>>
I'd have made a dictionary keyed by name with a list of scores as the value for each key, but your list of little dictionaries is workable. Good luck!
__________________
[code] Code tags[/code] are essential for python code!
|

November 4th, 2012, 06:27 PM
|
 |
Commie Mutant Traitor
|
|
Join Date: Jun 2004
Location: Norcross, GA (again)
|
|
Oh, this is actually pretty close, in a lot of ways. Unfortunately, it also shows a number of serious misunderstandings with how Python works, ones which newcomers often have but which you'll need to get past to finish the problem. Let's start with the bowling_scores() function. Here, the biggest issue IMHO is that you are using a list for the data, but then treating it as if it were a dictionary.
Code:
import sys
def bowling_scores(filename):
""" A function to collect the bowling scores
from the input file and returns it in a dictionary.
key == player's name
value == player's score
"""
try:
infile = open(filename, "r")
except:
print("Could not read file '{0}'. Exiting.".format(filename))
sys.exit(-1)
bowling_info = dict()
count = 0
for line in infile:
parts = line.split("\n")
count += 1
if count % 2 == 1:
name = parts[0] # odd line, get just the player's name
else:
score = int(parts[0]) # even line, get the player's score
bowling_info[name] = score # and store it in the dictionary keyed to name
infile.close()
return bowling_info
This was, I think, simply a confusion over what kind of data structure you were intending to use.
Note the use of the documentation string or docstring: if you put a string, either a regular one or a triple-quote multi-line string, immediately after the declaration part of a function, it is treated as the documentation for that function. The same applies to methods, classes, and modules, in fact.
For the second function, I think you are trying to fit too much into the same function, and getting snarled as a result. I would break it up into two functions, one of which simply returns the average, the other (which calls that function) which actually does the writing to the file.
Code:
def avg_score(scores):
""" Function which takes a dictionary of bowling player's names and scores
and returns the average of the scores (type float).
"""
denominator = len(scores)
numerator = 0
for name in scores.keys():
numerator += scores[name]
return numerator / denominator
def bowling_averages(scores):
""" Function that takes a scores dictionary
and returns a list of strings describing the score
relative to the average score.
"""
scoreAverage = avg_score(scores)
scoreDescriptions = list()
for player in sorted(scores.keys()):
score = scores[player]
description = ''
if score == 300:
description = "perfect"
elif score > scoreAverage:
description = "above average"
elif score == scoreAverage:
description = "average"
else:
description = "below average"
scoreDescriptions.append('{0}: {1}'.format(player, description))
return scoreDescriptions
Finally, you'll need to re-write the __main__ section to reflect the changes made:
Code:
if __name__ == "__main__":
scores = bowling_scores("bowlingscores.txt")
descriptions = bowling_averages(scores)
try:
outfile = open("bowlingaverages.txt", "w")
except:
print("Could not open file 'bowling_averages.txt'. Exiting.")
sys.exit(-1)
for line in descriptions:
print(line)
outfile.write(line + '\n')
outfile.close()
(NB: None of this is tested code, so I may well have made a mistake myself. Test it out careful before you submit anything.)
Last edited by Schol-R-LEA : November 4th, 2012 at 06:41 PM.
|

November 4th, 2012, 06:41 PM
|
|
Registered User
|
|
Join Date: Nov 2012
Posts: 16
Time spent in forums: 2 h 41 m 15 sec
Reputation Power: 0
|
|
I appreciate everyone's help! I'm learning a lot. I have to keep in mind that sometimes when I look at code written by people that have been doing this much longer than I have, I can't just copy what yalls code says. I have to truly sit down and learn what yall are saying, because I have to then take the concept of it and simplify it into a more beginner level code. Otherwise, my instructor would just think I copied someone and didn't learn anything.
I made some revisions, and this is the error I am getting:
line 35, in <module>
for key in sorted(bowling_avg):
TypeError: 'function; object is not iterable
My code reads:
Code:
def bowling_scores(filename):
infile = open(filename, "r")
bowling_info = []
count = 0
for line in infile:
parts = line.split("/n")
count += 1
if count == 1 or count % 2 == 1:
info = dict(name=parts[0])
if count % 2 == 0:
info["score"] = int(parts[0])
bowling_info.append(info)
infile.close()
return bowling_info
def bowling_avg(filename):
outfile = open(filename, "r")
bowling_avg = []
for key in sorted(bowling_info):
score = bowling_info["score"]
avg_score = (sum(score) / len(score))
avg = ""
if score == 300:
avg = "perfect"
bowling_avg.append(avg)
elif score > avg_score:
avg = "above average"
bowling_avg.append(avg)
elif score < avg_score:
avg = "below average"
bowling_avg.append(avg)
outfile.close()
return bowling_avg
outfile = open("bowling_avg", "w")
for key in sorted(bowling_avg):
outfile.write("%s %s\n" % (bowling_info[name], avg))
|

November 4th, 2012, 08:52 PM
|
 |
Contributing User
|
|
|
|
|
Perhaps my post was too subtle.
Where you have
for key in sorted(bowling_avg):
bowling_avg is a function. You didn't call the function to get its return value. How do we know? Of course the error message says so. I find that printing the type and value of the object in doubt right before the error helps.
print(str(type(bowling_avg)));print(str(bowling_avg))# new line 35
for key in sorted(bowling_avg):
That might help you understand a little bit.
Your bowling_avg function needs a string argument, which it uses to open a file for read access with the unlikely named variable "outfile" but you don't use outfile except to close it later. As scholar-LEA says, close but there's a lot of misunderstanding in there.
As I said before, passing the list of little dictionaries created by bowling_scores into bowling_avg makes a lot more sense. And as Scholar-LEA said, you'll need to change your main code to actually call bowling_scores. Defining a function doesn't invoke that function. You need to call the function, just like you knew to do with
open(filename, "r")
|

November 4th, 2012, 09:16 PM
|
|
Registered User
|
|
Join Date: Nov 2012
Posts: 16
Time spent in forums: 2 h 41 m 15 sec
Reputation Power: 0
|
|
|
Thanks, I see what your saying. Ill work on it some more and ill post what I come up with. I appreciate it.
|

November 5th, 2012, 09:01 PM
|
|
Registered User
|
|
Join Date: Nov 2012
Posts: 16
Time spent in forums: 2 h 41 m 15 sec
Reputation Power: 0
|
|
ok this is what I have come up with. I' afraid that I have gotten too lost and will have to just start fresh. What do you think?
Code:
def bowling_scores(filename):
infile = open(filename, "r")
bowling_info = []
count = 0
for line in infile:
parts = line.split("/n")
count += 1
if count == 1 or count % 2 == 1:
name = parts[0]
else:
score = int(parts[0])
bowling_info[name] = score
infile.close()
return bowling_info
def avg_score(scores):
denominator = len(scores)
numerator = 0
for name in scores.keys():
numerator += scores[name]
return numerator / denominator
def bowling_averages(scores):
scoreAverage = avg_score(scores)
scoreDescriptions = list()
for player in sorted(scores.keys()):
score = scores[player]
description = ''
if score == 300:
description = "perfect"
elif score > scoreAverage:
description = "above average"
elif score == scoreAverage:
description = "average"
else:
description = "below average"
scoreDescriptions.append('{0}: {1}'.format(player, description))
return scoreDescriptions
scores = bowling_scores("bowlingscores.txt")
descriptions = bowling_averages(scores)
outfile = open("bowling_avg.txt", "w")
for line in description:
outfile.write(line + "/n" )
outfile.close()
|

November 6th, 2012, 09:01 AM
|
 |
Contributing User
|
|
|
|
I think that you need to actually let python process your program. You'll soon start to learn how to use the python error messages.
I checked only Hector, your output was correct for Hector.
Anyway, you're program is now pretty close, I fixed it with small changes, and marked the lines I changed with comments. Please run your original program and try to figure out why the changes I made were important.
Also, I'm quite sure I can create an input file that will produce different answers when run on python2 versus python3. It may be subtle but in your next program you'll probably ask why 3/2 is 1.
Also, 1%2 is 1.
Also, your program limitation (based on the way I modified it) is one game per player. That might be given in the problem statement. Or you could call this a feature, saying that only the last entry per player is counted and therefor the input is particularly easy to edit.
Also, that's all the alsos.
Code:
import sys
def bowling_scores(filename):
infile = open(filename, "r")
bowling_info = dict() # was list() #[]
count = 0
for line in infile:
parts = line.split("/n")
count += 1
if count == 1 or count % 2 == 1:
name = parts[0]
else:
score = int(parts[0])
bowling_info[name] = score
infile.close()
return bowling_info
def avg_score(scores):
denominator = len(scores)
numerator = 0
for name in scores.keys():
numerator += scores[name]
return numerator / denominator
def bowling_averages(scores):
scoreAverage = avg_score(scores)
scoreDescriptions = list()
for player in sorted(scores.keys()):
score = scores[player]
description = ''
if score == 300:
description = "perfect"
elif score > scoreAverage:
description = "above average"
elif score == scoreAverage:
description = "average"
else:
description = "below average"
scoreDescriptions.append('{0}: {1}'.format(player, description))
return scoreDescriptions
if 'linux' in sys.platform:
filename = '/tmp/bs'
else:
filename = "bowlingscores.txt"
scores = bowling_scores(filename)
descriptions = bowling_averages(scores)
outfile = open("bowling_avg.txt", "w")
for line in descriptions: # descriptions was singular
outfile.write(line + "\n" ) # was "/n"
outfile.close()
|
Developer Shed Advertisers and Affiliates
| Thread Tools |
Search this Thread |
|
|
|
| Display Modes |
Rate This Thread |
Linear Mode
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|