# # Question 1 # # Part A # 3 points # # +1 correctly builds list as result (either using loop or list comprehension) # +1 correctly finds middle letter from only (and all) 5 letter words # +1 correctly assigns type (list of strings) and variable (no return) middles = [ w[2] for w in words if len(w) == 5 ] # Part B # 5 points # # +1 correctly builds list as result (either using loop or list comprehension) # +1 correctly finds only (and all) words with same start and end letters # +1 attempts to sort resulting list # +1 correctly sorts resulting list based on word length and reversed # +1 correctly assigns type (list of strings) and variable (no return) sameEnds = sorted([ w for w in words if w[0] == w[-1] ], key=len, reverse=True) # ALTERNATE SOLUTION sameEnds = sorted([w for w in words if w.endswith(w[0])], key=len, reverse=True) # Part C # 6 points # # +1 correctly builds list as result (either using loop or list comprehension) # +1 attempts to find words with unique letters # +2 correctly finds only (and all) words with unique letters # +1 correctly sorts resulting list # +1 correctly assigns type (list of strings) and variable (no return) unique = sorted([ w for w in words if len(set(w)) == len(w) ]) # ALTERNATE SOLUTION def allUnique (word): for letter in word: if word.count(letter) > 1: return False return True unique = sorted([ w for w in words if allUnique(w) ]) # Part D # 6 points # # +1 uses variable onebigword rather than individual words # +1 attempts to count each letter's occurrences (using count, dictionary) # +1 correctly counts each letter's occurrences # +1 attempts to find most common letter (using max or a loop) # +1 correctly finds most common letter # +1 correctly assigns type (string) and variable (no return) onebigword = "".join(words) mostCommon = max([ (onebigword.count(x), x) for x in set(onebigword) ])[1] # # Question 2 # # 3 points each # # +1 describes sequence in sufficient detail to understand its purpose # +1 explains how the sequence will be used to solve the problem # +1 description does not contain any obvious misuses of the sequence # (sets or dictionaries are ordered, tuples are mutable, etc.) # Part A # List of tuples (passenger ID, boarding order), where order could be # the seat, the "zone", time ticket was purchased, something that # could be the basis for sorting. # OR: # Dictionary whose keys are the boarding order and # values are a list of passenger IDs. # Note, just a list of passenger IDs with no explanation of how the order # was derrived loses 1 point. It does provide a "total" ordering but # no explanation of how it was acheived, so no way to "reuse" the sequence. # Part B # List of sets of each airport’s kinds of planes # (set could also contain tuples (plane kinds, count)) # OR: # Dictionary whose keys are plane types and # whose values are airports that have that plane # Part C # List of lists of passenger IDs (i.e., each sublist indicates a row, # and its elements are the passengers in the seats) # OR: # Dictionary whose keys are strings or tuples, row number and name, # and whose values are passenger IDs # Part D # List of tuples (passenger ID, departure time) # can be sorted based on departure time or minutes until departure # or something similar # OR: # Dictionary whose keys are a number, i.e., departure time, and # whose values are passenger IDs # # Question 3 # # 4 points each # # +1 correctly explains what the code does # +2 explains WHY the code works --- NOT just what it does # +1 explains how each solution is different # Part A # Lines 1-6 create a dictionary whose keys are an int, the ID of who # solved the task, and whose values are a list of ints, when those # tasks were solved. # Line 7 finds the most number of tasks solved (not who, just how many). # Line 8 sorts a list of only those contestants that solved the most # number of tasks by the order in which they solved the last task # (from earliest to latest). # Line 9 returns the winner's ID, the one that solved their last task first. # Part B # Line 1 finds the most number of tasks solved (not who, just how many). # Lines 2-6 create a dictionary whose keys are an int, the ID of who # solved the task, and whose values are an int, the number of tasks solved. # Lines 7-8 returns the winner's ID, the one that solved their last task first. # Note, this does require an else or return after the loop because # there is guaranteed to be at least one contestant who solved that # number of tasks and the if statement, being inside the loop, finds # the first such contestant to have done so. # Part C # Lines 1-2 creates a list of tuples of ints, (number of tasks solved, when # the last task was solved, contestant ID), for each unique contestant. # Line 3 returns the winner's ID, the one that solved their last task first. # Note, the max first compares the first item of the tuple, the # number of tasks solved, looking for the greatest. If those are equal, # then if compares the second item, when the task was solved. Since # the list was reversed, the earliest one completed will actually have # the greatest index. It will never compare the third items in the tuple # because the tasks were all completed in a unique order. # # Question 4 # # Part A # 2 points # # +1 explanation is based on the current data (i.e., I see 0s or I don't) # +1 explanation is based on why the statistics exist # Games played is not 0 for any player, while shot attempts are. # This is because a player cannot have any stats if they have not # played some minutes in at least one game. # Part B # 4 points # # +1 provide a reasonable explanation of the code # +1 notes that lists are mutable # +2 shows that there can be multiple names for the same list # currentStats and players[name] are two different names that both # reference the exact same list. Since lists are mutable, any changes # made using one of the names will be available using the other name. # Note, may also show a picture of the variable names with arrows # pointing to a single list of values. # Part C # 4 points # # +1 explains that formattedLines[0] is the header row # +1 explains what the function zip does (in context of problem) # +1 explains what the function dict does (in context of problem) # +1 explains why the first parameter includes the slice [1:] # A dictionary can be created from a list of tuples of 2 items, the # key and the value. The function zip creates a list of tuples of 2 # items, where the first item in each tuple is from the first list # given and the second item is from the second list given. Since the # first list given contains strings, the stat names from the header row # and the second list given contains ints, the value of the stat # associated with the player, the appropriate dictionary is created. # In order for the lists to be the same length, the NAME field of the # header row must be sliced off. # Part D # 6 points # # +1 uses stats dictionary properly # +1 attempts to check for divide by 0 error # +1 correctly checks for divide by 0 error # +1 correctly calls or calculates totalPoints # +1 correctly implements given formula # +1 correctly returns value in all cases def pointsPerScoringAttempt (stats): if stats['FGA'] == 0 and stats['FTA'] == 0: return 0 else: return totalPoints(stats) / (stats['FGA'] + 0.475 * stats['FTA']) # # Movie Problem 1 # # +10 passes all test cases and code looks right # +8 passes none or some test cases, but code only has a minor error # (e.g., off by one, no type conversion, bad initialization, etc) # +6 passes none or some test cases, but code has a major or logic error # (e.g., missed something in the problem, has a significant bug, etc) # +5 passes no test cases due to a fixable compilation error or exception, # code is significantly correct but may still have a major or minor error # +3 passes no test cases, but attempts in code or comments to solve problem # +0 no attempt or just returns [] or # contains conditions for specific test cases (other than empty cases) # # A dictionary accumulation loop based on some feature in the data # The basic structure is: # create empty dictionary # loop over all data elements # create key from current data element # if key has not been seen before initialize to 0 # add 1 to the key's total count # convert dictionary to a list or tuples (value, key) for sorting # return sorted results # For example: def firstNamesCast (movies, count): """ returns list of tuples (count, first name) """ namesCounts = {} for name in uniqueCastMembers(movies): key = name.split()[0] namesCounts[key] = namesCounts.get(key, 0) + 1 results = [ (v, k) for (k,v) in sorted(namesCounts.items()) ] return sorted(results, key=operator.itemgetter(0), reverse=True)[:count] # # Movie Problem 2 # # +20 passes all test cases and code looks right # +17 passes none or some test cases, but code only has a minor error # (e.g., off by one, no type conversion, bad initialization, etc) # +14 passes none or some test cases, but code has a major or logic error # (e.g., missed something in the problem, has a significant bug, etc) # +10 passes no test cases due to a fixable compilation error or exception, # code is significantly correct but may still have a major or minor error # +6 passes no test cases, but attempts in code or comments to solve problem # +0 no attempt or just returns [] or # contains conditions for specific test cases (other than empty cases) # # Use dictionary to organize the movie information to answer a question. # For example: def averageRatingByYear (movies, count): """ returns list of tuples (average rating, year) """ yearlyRatings = {} for (k,v) in movies.items(): key = k[1] value = float(v[8]) if value < 10: yearlyRatings[key] = yearlyRatings.get(key, []) + [value] results = sorted([(sum(v) / len(v), k) for (k,v) in yearlyRatings.items()]) return sorted(results, key=operator.itemgetter(0), reverse=True)[:count]