# Arup Guha
# 10/27/2020
# A test to show difference in run time when the max function is called once
# versus many times/

import random

# Returns the number of As in the class with scores.
def countAs(scores):

    # Get the top score.
    topScore = max(scores)

    # Set up our accumulator.
    numAs = 0

    # Go through each score.
    ''' Key notice is that max isn't called in this loop at all, instead
        we have stored the value max returns in the variable topScore
        which is fast to look up.
    '''
    for x in scores:

        # See if this one is within 10 pts of the top.
        if x >= topScore-10:
            numAs += 1

    return numAs

# Returns the number of As in the class with scores.
def countAsAlt(scores):

    # Set up our accumulator.
    numAs = 0

    # Go through each score.
    for x in scores:

        ''' The for loop is running len(scores) times and then the
            max function has a for loop in it also running len(scores)
            times. So if len(scores) is 50,000, we are talking about
            2,500,000,000 operations, while the regular countAs is doing
            50,000 + 50,000 = 100,000, roughly.
        '''
        # See if this one is within 10 pts of the top.
        if x >= max(scores)-10:
            numAs += 1

    return numAs

# Our test.
def main():

    vals = []
    for i in range(50000):
        vals.append(random.randint(1,100))

    # Call whichever function you want and watch how long it takes =)
    print(countAsAlt(vals))

# Run it.
main()
