HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Validating and averaging student grades

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gradesstudentaveragingvalidatingand

Problem

I have myself a little challenge tonight. I've tried to come up with the shortest code for the problem below (the code is pretty self explanatory, except determinGrade there which follows the rule


A - 90-100%

B - 80-89%

C - 70-79%

D - 60-69%

F - Below 60%

The code has to be PEP8 complient and no imports (std included) are allowed. Tell me if you can shorten the code further.

isValidScore = lambda n: 0 <= n <= 100
calcAverage = lambda *args: sum(args)/len(args)
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, (min(s, 99)/10)-5)]

def getValidScore():
    while True:
        try:
            s = int(raw_input('Input score: '))
            if isValidScore(s):
                return s
        except ValueError:
            pass
        print('Score has to be an integer in the range 0 to 100')

if __name__ == "__main__":
    scores = [getValidScore() for _ in range(5)]
    print('The scores are: ' + str(scores))
    print('The average is: ' + str(calcAverage(*scores)))
    print('The grade is: ' + determinGrade(calcAverage(*scores)))

Solution

Although this passes the pep8 tool as of version 1.5.5,
this is not PEP8 compliant:



  • Function names should be lowercase, with words separated by underscores as necessary to improve readability.



  • Always use a def statement instead of an assignment statement that binds a lambda expression directly to an identifier.




If you convert the lambda expressions to def statements, the result will be longer, but better.

Also, these statements are a bit tightly packed for my taste:

calcAverage = lambda *args: sum(args)/len(args)
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, (min(s, 99)/10)-5)]


Would have been better this way, but PEP8 does not require it:

calcAverage = lambda *args: sum(args) / len(args)
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, (min(s, 99) / 10) - 5)]


In this last statement, there are some redundant parentheses, this is equivalent:

determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, min(s, 99) / 10 - 5)]


Instead of the min hack for the value of 100, how about this way:

determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A', 'A'][max(0, s / 10 - 5)]


Last but not least, beware that in Python 3, 27 / 10 will give you 2.7 instead of 2 as in Python 2. As such, the determinGrade will try to use a float as the list index, and your script will break. Adopting Python 3 is probably only a matter of time, so it's good to be prepare for that, and use // to ensure that you will get an integer index:

determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A', 'A'][max(0, s // 10 - 5)]


Suggested implementation

Putting the above suggestions together:

def is_valid_score(n):
    return 0 <= n <= 100

def calc_average(*args):
    return sum(args) / len(args)

def determine_grade(s):
    return ['F', 'D', 'C', 'B', 'A', 'A'][max(0, s // 10 - 5)]

def get_valid_score():
    while True:
        try:
            s = int(raw_input('Input score: '))
            if is_valid_score(s):
                return s
        except ValueError:
            pass
        print('Score has to be an integer in the range 0 to 100')

if __name__ == "__main__":
    scores = [get_valid_score() for _ in range(5)]
    print('The scores are: ' + str(scores))
    print('The average is: ' + str(calc_average(*scores)))
    print('The grade is: ' + determine_grade(calc_average(*scores)))

Code Snippets

calcAverage = lambda *args: sum(args)/len(args)
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, (min(s, 99)/10)-5)]
calcAverage = lambda *args: sum(args) / len(args)
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, (min(s, 99) / 10) - 5)]
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A'][max(0, min(s, 99) / 10 - 5)]
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A', 'A'][max(0, s / 10 - 5)]
determinGrade = lambda s: ['F', 'D', 'C', 'B', 'A', 'A'][max(0, s // 10 - 5)]

Context

StackExchange Code Review Q#66821, answer score: 4

Revisions (0)

No revisions yet.