12 Replies - 976 Views - Last Post: 18 February 2013 - 07:02 AM Rate Topic: -----

#1 Suidomso  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 16-February 13

Calculating Grade from Input File

Posted 16 February 2013 - 07:14 PM

I'm trying to make a program using a text file. The text file has 3 student numbers and a few graded assignment (with weights). I'm not asking for anyone to do it by any means. I'm just confused as to how to go about it I guess. I've spent countless hours past few nights reading through books, watching YouTube videos, and reading websites with not much to show for it.

Only thing I have really is:

myFile = open("input.txt", "r")
numVals = int(myFile.readline())


I've tried doing variations of :

with open("file.txt", "r") as inFile:
    for line in inFile: 


sum=0
for i in range(numVals):
    num= (int(myFile.readline())
    sum= 


I've tried separating the names and grades, by specifying the line then adding to it (ex. Names are odd, +2 so it'll always have name), but nothing. I've also tried messing with splits, and that seems to be what I need to be using, so I'm going to continue messing around with that.

The other thing that has me confused is, that is probably much simpler than I'm making it out to be, is the formula. If I have a formula to use the grades for the text, how do I make it plug it in into the correct places? I tried assigning each variable and then finding which segments of the lines are for which variable, but that sees to defeat the purpose of using the text file.

Again, I'm really not looking for an answer to this. I'm just looking for advice to point me in a direction or something to read up on. I'm just tired of being frustrated. Haha

Is This A Good Question/Topic? 0
  • +

Replies To: Calculating Grade from Input File

#2 lisperati  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 16-February 13

Re: Calculating Grade from Input File

Posted 16 February 2013 - 09:17 PM

myFile = open("input.txt", 'r')
sum = 0
linecount = 1
for line in myFile:
    if linecoung % 2 == 0:
        #even linecount must be a grade
        numVals = int(line)
        sum += numVals 
        print "Student Name: ",name," Grade: ",grade 
    else:
        #odd linecount must be a name as specified in program design statement
        name = line
        sum = 0

    linecount += 1
    





OK , this sort of thing should work if the name is first on line one then the grade on line 2 and so on, and if there is only one grade per line. If there are many grades on the line you will have to separte them like so:

if linecoung % 2 == 0:
        #even linecount must be a grade
        #assume multiple values and separted by a comma
        sum = 0
        numVals = ""
        for char in line:
            if char == ",":
                #if comma then you have complete value, iterate over comma but save current number to sum
                sum += int(numVals)
            else:
                #if not a comma then it must be part of the number
                numVals += char   
        print "Student Name: ",name," Grade: ",grade 



Avoid the temptation to use split for your homework or assignment as that doesnt show you actually understand what is happening or that you can code a solution. Also if you get an error using split it can be a nightmare to track it down.
With this sort of code its all yours and you can look to see if it all works and where it doesnt if it fails. This is what i used to get values from a comma separated file from the internet and it works on all files. Also it gives you an appreciation for actually how much code goes into getting data from datasources so when you use something like sql and see how fast it retrieves and sets records you can literally be amazed as you know the sort of code it is using but still is able to process millions of records instantly.

Anyway hope this helps your project.

Regards
Lisperati
Was This Post Helpful? 0
  • +
  • -

#3 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: Calculating Grade from Input File

Posted 17 February 2013 - 02:17 AM

@lisperati
Firstly, students should always be instructed to use with/as when opening/closing files.

Secondly sum is a built in function that finds the sum of values in an iterable. It should never be used as a variable name or when you try to use it as a function this happens:
>>> sum((1,2,3,4,5))
15
>>> sum = 0
>>> sum((1,2,3,4,5))

Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    sum((1,2,3,4,5))
TypeError: 'int' object is not callable
>>> 

Thirdly, if you want a counter when looping over an iterable use enumerate. This is Python not C:
with open("file.txt",'r') as myfile:
    for linenum,line in enumerate(myfile):
        #do stuff here


And lastly, advising someone not to use split in python is nonsense. Split is a very powerful tool for text parsing and if the situation calls for it, it is what should be used. If I give you a text file with numbers separated by commas or spaces, and you need to extract that information, you would be an idiot not to use split. Using split shows a hell of a lot more understanding of python than what you have done.

Anyway...
@Suidomso
Take another shot at it and then repost including an example of what the file you are parsing looks like, as well as exactly what your output should look like.

-Mek
Was This Post Helpful? 0
  • +
  • -

#4 lisperati  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 16-February 13

Re: Calculating Grade from Input File

Posted 17 February 2013 - 07:32 AM

@Mek

greavy
42,89,90
sauvy
48,85,98
harry
90,90,90



Ok then, here is the test data ive made up as per requirements from the original post. simple hey?

scores = open("scores.txt",'r')
linecount = 1
stu = []
real = []
for line in scores:
    if linecount % 2 == 0:
        tent = line.split(",")
        stu.append(name.strip('\n'))
        stu.append(tent[0])
        stu.append(tent[1])
        stu.append(tent[2].strip('\n'))
        real.append(stu)
    else:
        name = line

    linecount += 1
    stu = []
    tent = ""



for student in real:
    total = int(student[1]) + int(student[2]) + int(student[3])
    print "Name: ",student[0]," Total: ",total," Average: ",total / 3



This program has been unit tested to precisely work with the data and contains no additional unnecessary fluffy functions and omits the variable sum.

Considering the problem domain and the ability of the said student, do we really need to argue about how to do this homework using advanced functions said student probably doesnt understand?

How much speed do we lose this way compared to your functional analysis?
How many more lines of code does your preferred way entail?

As a computer scientist who regularly teaches children python, I am sure simple is best and short simple programs are easier to learn. Advanced functions are good when the level of competance improves enough to understand systems a bit better.

Please consider your subject before you run to inject more than a necessary amount of content.

Regards
Lisperati
Was This Post Helpful? 0
  • +
  • -

#5 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: Calculating Grade from Input File

Posted 17 February 2013 - 08:50 AM

I would have a debate with you about it but considering the condescension and the attempt to drop, "As a computer scientist who regularly teaches children python," as something I should care about, I'll say this instead.

If you think you should initialize a counter before a for loop in python, you shouldn't be teaching it to anyone.

If you think that this,
print "Name: ",student[0]," Total: ",total," Average: ",total / 3
is a good example of a print statement, you shouldn't be teaching it to anyone.

There is a difference between teaching "simple" and teaching bad habits.
Anyway I will leave it at that and reserve future comments for the OP.

-Mek
Was This Post Helpful? 0
  • +
  • -

#6 Suidomso  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 16-February 13

Re: Calculating Grade from Input File

Posted 17 February 2013 - 01:58 PM

Thanks all for the help! It seems like I was over-complicating this by a lot, haha. I'll now dive into it with my newly acquired information =D

Thanks again! I'll post when I get it.
Was This Post Helpful? 0
  • +
  • -

#7 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: Calculating Grade from Input File

Posted 17 February 2013 - 05:26 PM

My (apparently) overly complicated way of doing this:
students = {}   #Create an empty dictionary
with open("scores.txt",'r') as scores:   #Use with/as for safe opening/closing
    for linenumber,line in enumerate(scores):   #Iterate using enumerate
        line = line.strip()   #Strip before doing anything with the line
        if line:   #Ignore blank lines that might exist at end of file
            if not linenumber%2:   #Don't test against 0, use not instead
                name = line
            else: #The else clause here uses a list comprehension.
                students[name] = [int(score) for score in line.split(',')]

for stud in students:  #Iterate over created dictionary
    tot = sum(students[stud]) #The convenient sum function makes life easy.
    avg = tot/float(len(students[stud])) #Make sure you aren't doing integer division (py2.x)
    print("Name: {:10} Total: {:<10} Average: {:.2f}".format(stud,tot,avg))

This creates an organize dictionary of the information. Dictionaries are nice for this sort of thing.
-Mek
Was This Post Helpful? 0
  • +
  • -

#8 lisperati  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 16-February 13

Re: Calculating Grade from Input File

Posted 17 February 2013 - 05:59 PM

Look forward to seeing your final code Suidomso.

Regards
Lisperati
Was This Post Helpful? 0
  • +
  • -

#9 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: Calculating Grade from Input File

Posted 18 February 2013 - 03:02 AM

lisperati said:

How much speed do we lose this way compared to your functional analysis?
How many more lines of code does your preferred way entail?

I decided to look at how fast some of these algorithms actually did compare performance wise.

Firstly I wrote a short program to generate a large file of your prescribed format (as three entrees doesn't show the comparison well.):
import random

with open("myscores.txt",'w') as myfile:
    for i in range(10000):
        name = ""
        for j in range(6):
            char = random.choice(list(range(65,91))+list(range(97,123)))
            name += chr(char)
        grades = random.randint(0,101),random.randint(0,101),random.randint(0,101)
        myfile.write("{}\n{},{},{}\n".format(name,*grades))
This generates 10,000 students and corresponding grades on three assignments.

I timed three algorithms. My method generating a dict, your method, and a third method I wrote which is extremely short but proportionately inefficient the larger the file size. I timed these by wrapping the code as follows:
import time
start = time.clock()

#code to time here.

print("Time: {:.5} seconds".format(time.clock()-start))
My method stated in my previous post averaged 3.11 seconds and took 13 lines of code. My alternate method is 7 lines long and averaged 3.16 seconds. Your method, without alterations is 20 lines of code and averaged 18.45 seconds.

The irony however is, that it isn't your algorithm itself that is slowing you down, but your print statement.
By replacing your print statement from:
print "Name: ",student[0]," Total: ",total," Average: ",total / 3
to this:
print("Name: {} Total: {} Average: {}".format(student[0],total,total / 3))
your average dropped to 3.17 seconds. As my averages were only over three sets we can conclude that the three algorithms are, if the print statement is fixed, essentially equivalent performance-wise.(Note that the print statements in general are what take all the time; if we just do all the calculations without printing the times drop to about 0.07 seconds.

I hope this convinces you to if nothing else, use (and teach) properly formatted print statements.

If you are interested in my 7 line method here it is. Note: I absolutely wouldn't suggest this method to a beginner, but for a competent python programmer it is still pretty clear:
with open("myscores.txt",'r') as scores:
    data = [score.strip() for score in scores.readlines() if score.strip()]
students = zip([d for d in data[::2]],[d.split(',') for d in data[1::2]])
for stud in students:
	tot = sum((float(num) for num in stud[1]))
	items = (stud[0],tot,tot/len(stud[1]))
	print("Name: {:10} Total: {:<10.2f} Average: {:>6.2f}".format(*items))
This use of readlines() and zip works very well but unfortunately it requires that the entire file be loaded into memory all at once. As such if you know your files won't get bigger than a certain size it is fine, but for arbitrarily large files it is a bad idea.

-Mek
Was This Post Helpful? 0
  • +
  • -

#10 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: Calculating Grade from Input File

Posted 18 February 2013 - 03:02 AM

Edit: Forum posted my reply twice; apologies.

This post has been edited by Mekire: 18 February 2013 - 03:07 AM

Was This Post Helpful? 0
  • +
  • -

#11 andrewsw  Icon User is offline

  • Fire giant boob nipple gun!
  • member icon

Reputation: 3331
  • View blog
  • Posts: 11,261
  • Joined: 12-December 12

Re: Calculating Grade from Input File

Posted 18 February 2013 - 03:21 AM

You could skip the packing and unpacking:

print("Name: {:10} Total: {:<10.2f} Average: {:>6.2f}".format(stud[0],tot,tot/len(stud[1])))

Was This Post Helpful? 0
  • +
  • -

#12 Mekire  Icon User is offline

  • D.I.C Head

Reputation: 116
  • View blog
  • Posts: 212
  • Joined: 11-January 13

Re: Calculating Grade from Input File

Posted 18 February 2013 - 03:36 AM

View Postandrewsw, on 18 February 2013 - 03:21 AM, said:

You could skip the packing and unpacking:

print("Name: {:10} Total: {:<10.2f} Average: {:>6.2f}".format(stud[0],tot,tot/len(stud[1])))
Yeah I know; I just don't like the way it shows up on two lines on the forum. Also I wanted to keep it somewhat reasonable; you can save a couple more lines too but it starts to get pretty silly.

-Mek
Was This Post Helpful? 0
  • +
  • -

#13 lisperati  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 10
  • Joined: 16-February 13

Re: Calculating Grade from Input File

Posted 18 February 2013 - 07:02 AM

@Mek

Seriously, I cant believe you even bothered. Are you actually for real?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1