Week 5 Tutorial: Lists
Problem 1: Finding the Top Performer
Problem Statement:
You are a teaching assistant and need to find the student with the highest score from a recent exam. You are given two lists: one with student names and another with their corresponding scores. The lists are “parallel,” meaning the student at index i in the student_names list earned the score at index i in the student_scores list.
Write a Python function called find_best_student(student_names, student_scores) that takes these two lists as arguments.
Requirements:
- The function should determine the highest score in the
student_scoreslist. - It should then find the name of the student who achieved that score.
- The function must return the name (a string) of the student with the highest score.
Constraints & Edge Cases:
- If the input lists are empty, the function should return
None. - In case of a tie for the highest score, the function should return the name of the first student who achieved that score.
- You can assume both lists will always have the same number of elements.
Example Cases:
names = ["Alice", "Bob", "Charlie", "David"]scores = [88, 92, 99, 95]-
Calling
find_best_student(names, scores)should return"Charlie". names = ["Eve", "Frank", "Grace"]scores = [95, 85, 95]-
Calling
find_best_student(names, scores)should return"Eve"(due to the tie-breaker rule). names = []scores = []- Calling
find_best_student(names, scores)should returnNone.
Expected Output/Behavior:
Top student is: Charlie
Top student in a tie is: Eve
Result for empty lists: None
Problem 2: In-Place Data Cleaning
Problem Statement: In data analysis, it’s common to clean a dataset by removing invalid entries. You are tasked with writing a function that removes “outliers” from a list of measurements.
Write a Python function called remove_outliers(data, min_val, max_val) that modifies a list of numbers in-place.
Requirements:
- The function takes a list of numbers (
data), a minimum valid value (min_val), and a maximum valid value (max_val). - It should iterate through the
datalist and remove any number that is less thanmin_valor greater thanmax_val. - The list must be modified directly. The function should not create a new list and should not return any value.
Important Hint: Be careful when removing elements from a list you are iterating over. Using a standard for item in data: loop can lead to skipping elements. Consider using a while loop with an index.
Example Cases:
measurements = [8, 5, 12, 1, 9, 20, 15]-
Calling
remove_outliers(measurements, 5, 15)should change themeasurementslist to be[8, 5, 12, 9, 15]. temps = [-5, 10, 0, 35, 15, 40, 20]-
Calling
remove_outliers(temps, 0, 30)should change thetempslist to be[10, 0, 15, 20]. edge_case = [100, 1, 101, 2, 102]- Calling
remove_outliers(edge_case, 0, 10)should changeedge_caseto be[1, 2]. This case is designed to fail if you use a simpleforloop.
Expected Output/Behavior:
Original measurements: [8, 5, 12, 1, 9, 20, 15]
Cleaned measurements: [8, 5, 12, 9, 15]
--------------------
Original temps: [-5, 10, 0, 35, 15, 40, 20]
Cleaned temps: [10, 0, 15, 20]
--------------------
Original edge case: [100, 1, 101, 2, 102]
Cleaned edge case: [1, 2]
Problem 3: Zigzag Merge
Problem Statement:
Write a function called zigzag_merge(list1, list2) that takes two lists of items as input. The function should create and return a new list by merging the two input lists in a “zigzag” or alternating pattern.
Requirements:
- The new list should start with the first element of
list1, followed by the first element oflist2, then the second element oflist1, the second element oflist2, and so on. - The function should be able to handle lists of unequal length. Once the shorter list runs out of elements, the function should append all the remaining elements from the longer list to the end of the merged list.
- The original input lists should not be modified.
Example Cases:
list_a = [1, 2, 3]list_b = ['A', 'B', 'C']-
Calling
zigzag_merge(list_a, list_b)should return[1, 'A', 2, 'B', 3, 'C']. list_c = [1, 2]list_d = ['A', 'B', 'C', 'D']-
Calling
zigzag_merge(list_c, list_d)should return[1, 'A', 2, 'B', 'C', 'D']. list_e = [1, 2, 3, 4, 5]list_f = ['A']- Calling
zigzag_merge(list_e, list_f)should return[1, 'A', 2, 3, 4, 5].
Expected Output/Behavior:
Merged equal lists: [1, 'A', 2, 'B', 3, 'C']
Merged with longer second list: [1, 'A', 2, 'B', 'C', 'D']
Merged with longer first list: [1, 'A', 2, 3, 4, 5]
Problem 4: Longest Consecutive Run
Problem Statement:
Write a Python function called find_longest_run(data) that takes a single list of items (data) as an argument. The function should find the longest “run” of consecutive, identical elements and return the length of that run.
Requirements:
- A “run” is a sequence of one or more identical elements that appear next to each other.
- The function must return an integer representing the length of the longest run found in the list.
- If multiple runs have the same maximum length, the function can simply return that length.
Constraints & Edge Cases:
- If the input list is empty, the longest run is
0. - If the list has no repeated consecutive elements (e.g.,
[1, 2, 3, 4]), the longest run is1. - The function should correctly handle cases where the longest run occurs at the very beginning or the very end of the list.
Example Cases:
find_longest_run([1, 2, 2, 3, 3, 3, 2, 2])should return3(because of the three consecutive3s).find_longest_run(['A', 'A', 'A', 'B', 'C', 'C'])should return3(for the threeAs).find_longest_run([5, 5, 5, 5, 5])should return5.find_longest_run([1, 2, 3, 4, 5])should return1.find_longest_run([])should return0.
Expected Output/Behavior:
Longest run in [1, 2, 2, 3, 3, 3, 2, 2]: 3
Longest run in ['A', 'A', 'A', 'B', 'C', 'C']: 3
Longest run in [5, 5, 5, 5, 5]: 5
Longest run in [1, 2, 3, 4, 5]: 1
Longest run in []: 0
Problem 5: Data Smoothing (Moving Average)
Problem Statement: In data science, noisy data is often “smoothed” to reveal trends. A common technique is the Simple Moving Average.
Write a function called calculate_moving_average(data, window_size) that takes a list of numbers (data) and an integer (window_size).
Requirements:
- The function should calculate the average of every consecutive “window” of
window_sizeelements in the list. - For example, if
window_sizeis 3, you first average elements at indices0, 1, 2, then average elements at1, 2, 3, then2, 3, 4, and so on, until you reach the end of the list. - Return a new list containing these calculated averages.
Constraints & Edge Cases:
- If the
window_sizeis greater than the total length of thedatalist, the function cannot calculate any full windows. It should return an empty list[]. - If
window_sizeis less than or equal to 0, it should also return an empty list[].
Example Trace:
If data = [10, 20, 30, 40, 50] and window_size = 3:
- Window 1:
[10, 20, 30]-> Average is(10+20+30)/3=20.0 - Window 2:
[20, 30, 40]-> Average is(20+30+40)/3=30.0 - Window 3:
[30, 40, 50]-> Average is(30+40+50)/3=40.0 - Result:
[20.0, 30.0, 40.0]
Example Cases:
calculate_moving_average([1, 2, 3, 4, 5], 2)should return[1.5, 2.5, 3.5, 4.5].calculate_moving_average([10, 20, 30, 40, 50], 3)should return[20.0, 30.0, 40.0].calculate_moving_average([5, 10, 15], 5)should return[](window too large).calculate_moving_average([8, 12], 1)should return[8.0, 12.0](window of size 1 is just the numbers themselves).
Expected Output/Behavior:
Moving average (window 3) of [10, 20, 30, 40, 50]: [20.0, 30.0, 40.0]
Moving average (window 2) of [1, 2, 3, 4, 5]: [1.5, 2.5, 3.5, 4.5]
Moving average (window 5 - too big) of [5, 10, 15]: []
This content will be available starting October 30, 2025.