House Point Program

Question:

My name is Jamie, I’m a Yr 12 student currently living in NZ. At school, in our computer science class we were tasked with creating a program for house points. A house is sort of like the Houses in Harry Potter, each student is assigned to one. These houses then compete in events and earn points, at the end of the year the house with the most points wins the trophy.

Now we have only been taught about 2-D arrays and parallel lists, as these need to be incorporated plus it must be modular.

The program must be fully user inputed as requirements for excellence (equivalent of A) must be user inputed.

The program must also have these inputs and outputs:

Inputs: House Names, House Events, and Points earned in events for the house

Cancel house name and house event entry when XXX is entered.

Outputs: Winner of each event, house with best average, house with most wins, and overall winner.

I am currently trying to figure out how to do the points to go with house and events.

Appreciate all help,

Jamie 🙂

EDIT: Posted Code

 def number_house():
    global numhouse
    print("Welcome!")
    print()
    Flag = True#loop
    while Flag:
        try:
            numhouse = int(input("Please enter the number of events there is: "))
            print()
            if numhouse < 1 or numhouse > 100:
                print("WOW, thats a lot of events, please be reasonable. Thanks.")
            else:
                Flag = False
        except ValueError:
            print("Enter only a number, Thanks.")

def event_names():
    global event
    print("Enter XXX when finished entering event names")
    Flag = True
    for e in range(numhouse):
        e = input("Event name: ")
        if e == 'XXX' or e == 'xxx':
            Flag = False
        else:
            event.append(e)
    print()
def getData():
    global data
    global inputlist
    global event
    lower_bound = 0
    upper_bound = 100
    k=0
    n=str(input("Please enter house names <<<Enter XXX when finished>>> :"))
    while n != 'XXX' :
        if n == 'XXX' or n == 'xxx':
            exit
        data = [n]
        print()
        print ("Please enter the event points in ascending order. ",event,"Thanks")
        for k in range(len(event)):
            s = getScore(n,lower_bound,upper_bound)
            data=data+[s]
            
        inputlist = inputlist + [data]
        n=str(input("Please enter house names <<<Enter XXX when finished>>> :"))


def getScore(name,min,max):
    global event
    sc= -1
    while sc < min or sc > max :
        try :
            sc = int(input("Please enter score for "+ name + " :"))
        except ValueError :
            print("Invalid Input please enter an interger. Thanks")
        
    return sc

score =[]
getscore = []
data = []
inputlist = []
event = []
number_house()
event_names()
getData()
print()
print(inputlist)
Asked By: matt

||

Answers:

I’ll try to give you a different approach, see if that helps you.

def main():
    events = []
    houses = []
    scores = {} # key = House name, value = scores

    print "Welcome!n"

    # create the houses
    print "Please enter how many houses there is:"
    n_houses = int(raw_input(">>"))

    print "Please enter houses names:"
    for n in range(n_houses):
        print "House", n+1
        house_name = raw_input(">>")
        houses.append(house_name)

    # create the events
    print "Please enter the number of events there is"
    n_events = int(raw_input(">>"))

    print "Please enter the event names"
    for n in range(n_events):
        print "Event", n+1
        event_name = raw_input(">>")
        events.append(event_name)

    # get the scores for each house for each event
    for event in events:
        for house in houses:
            print "Please enter the score for House %s in the event %s"%(house, event)
            score = int(raw_input(">>"))

            # initialize the score with a empty list
            if house not in scores:
                scores[house] = []

            # add the score list
            scores[house].append(score)

    print "nThe result is:"

    # process the result
    for house, score in sorted(scores.items(),
                                key=lambda x: sum(x[1]),
                                reverse=True):

        print "House %s. Total Score: %i"%(house, sum(score))


if __name__ == "__main__":
    main()

First thing you should notice is that I’m not using global, using global is usually frowned upon, it can lead to undesired interactions on data.

Also, instead of asking for inputs like “XXX” to break the loop, I asked the user for the number of inputs he wants to deal before, so I can loop over this number and process each separately.

I do the same thing with the house, I ask for how many houses are there, and then their names.

Next I do a nested for loop with the event names and house names. The order matters, we deal with each event first. You can change it to deal with each house first.

And finally I process the scores. the line for house, score in sorted(scores.items(), key=lambda x: sum(x[1]), reverse=True): is a bit clogged and advanced but it means this: I want to loop over a sorted list of items, giving me two items at a time, the items are named house and score, they will be sorted by the function sum(x[1]), and I want this in the reversed order (or else the last would show in first).

key=lambda x: sum(x[1]) is a bit of a hack, it could be done better. lambda means a function, it takes x as input, x in this case is a tuple of house, score, so I want the score, so I access it using x[1], and since I want the sum I use sum(x[1]).

Usage:

Welcome!

Please enter how many houses there is:
>>2
Please enter houses names:
House 1
>>Gryffindor
House 2
>>Slytherin
Please enter the number of events there is
>>2
Please enter the event names
Event 1
>>Quidditch Match
Event 2
>>Duels
Please enter the score for House Gryffindor in the event Quidditch Match
>>100
Please enter the score for House Slytherin in the event Quidditch Match
>>90
Please enter the score for House Gryffindor in the event Duels
>>250
Please enter the score for House Slytherin in the event Duels
>>240

The result is:
House Gryffindor. Total Score: 350
House Slytherin. Total Score: 330

Notice that this was made on Python 2.7, to port to Python 3 just change raw_input to input and print to print()

Answered By: f.rodrigues
LOWER_BOUND = 0   
UPPER_BOUND = 100  # both in caps because this is a constant

def get_score(house_name, event_name):
    # an extra argument so you can tell which event is being scored.
    # removed the min, max cause we are using the constants!
    score = -1
    while score < LOWER_BOUND or score > UPPER_BOUND:
        try:
            score = int(input("Please enter score for %s in the event %s:" % (house_name, event_name)))
            if score < LOWER_BOUND :
                print ("Score is too low, minimum score is %i.nPlease try again." % min_score)
            if score > UPPER_BOUND:
                print ("Score is too high, maximum score is %inPlease try again." % max_score)
        except ValueError:
            print("Invalid Input please enter an integer. Thanks")
    return score  # note the use of return to avoid using global

def get_number_of_events():
    print("Please enter the number of events there is.")
    while True:
        try:
            n_events = int(input(">>"))
        except ValueError:
            print("Enter only a number, Thanks.")
        if n_events > 100:
            print("WOW, that's a lot of events, please be reasonable. Thanks.")
        elif n_events < 1:
            # this is a different condition that would get a wrong error in your program, 
            # note the use of 'elif', in Python this an 'else if'.
            print ("That's too few events! Try Again.")
        else:
            # no need to use Flag, just use break when you want to leave a loop.
            break
    return n_events

def get_events_names(n_events):
    print ("Please enter the events names")
    events = []
    for n in range(1, n_events + 1):
        # starting at 1 to give a better display
        event_name = input("Event %i name: " % n)
        events.append(event_name)
    return events

def get_data(events):
    data = []
    while True:
        house_name = input("Please enter house names <<<Enter XXX when finished>>> :")
        if house_name.upper() == "XXX":
        # using .upper() to avoid checking twice for either 'xxx' or 'XXX'. 
        # I would ask the user for how many houses are there instead, but your choice ;)
            break

        print ("Please enter the events points in ascending order.")
        # not actually need to be in ascending order, you can sort them later if you want.
        scores = []
        for event_name in events:
            # don't use range(len(something)), loops in Python are easy!
            score = get_score(house_name, event_name)
            scores.append([event_name, score])
        data.append([house_name, scores])
        # use .append() instead of data = data + [...]
    return data


def main():
    print("Welcome!n")

    n_events = get_number_of_events()
    events_names = get_events_names(n_events)
    print()
    data = get_data(events_names)
    print()
    for house_name, event_data in data:
        print ("House " + house_name)

        for event_name, score in event_data:
            # note the use of tuple unpacking 
            print ("tEvent: %s Score: %i" % (event_name, score))

if __name__ == '__main__':
    main()

This time maintaining the same structure as your program.

Check comments for some tips and tricks.

Also, try to keep your variable names with meaning and check the PEP 8 guidelines for naming conventions (variables and functions should be snake_case,

Output:

Welcome!

Please enter the number of events there is.
>>2
Please enter the events names
Event 1 name: Quidditch Match
Event 2 name: Duels

Please enter house names <<<Enter XXX when finished>>> :Gryffindor
Please enter the events points in ascending order.
Please enter score for Gryffindor in the event Quidditch Match:100
Please enter score for Gryffindor in the event Duels:30
Please enter house names <<<Enter XXX when finished>>> :Slytherin
Please enter the events points in ascending order.
Please enter score for Slytherin in the event Quidditch Match:40
Please enter score for Slytherin in the event Duels:50
Please enter house names <<<Enter XXX when finished>>> :XXX

House Gryffindor
    Event: Quidditch Match Score: 100
    Event: Duels Score: 30
House Slytherin
    Event: Quidditch Match Score: 40
    Event: Duels Score: 50
Answered By: f.rodrigues
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.