Week 14 Tutorial: Intermediate Data Structures & Pythonic Coding
Problem 1: The Ingredient Checker
Problem Statement: You are writing a helper function for a cooking app. Users have a list of ingredients currently in their fridge (“pantry”), and they want to cook a specific recipe that requires a list of items (“recipe”).
Write a function check_ingredients(pantry_list, recipe_list) that compares the two lists and returns two specific lists:
- missing_items: Ingredients the user needs to buy (items in the recipe but NOT in the pantry).
- available_items: Ingredients the user already has for this recipe (items in both the recipe AND the pantry).
Requirements:
- The input lists might contain duplicates (e.g., user added “eggs” twice) - handle this using Sets.
- The input lists might have inconsistent casing (e.g., “Eggs” vs “eggs”). Convert everything to lowercase before comparing.
- The returned lists must be sorted alphabetically.
Test Case:
pantry = ["Eggs", "flour", "Milk", "eggs", "salt"]
recipe = ["flour", "milk", "Sugar", "Eggs", "butter"]
missing, available = check_ingredients(pantry, recipe)
print(f"Need to buy: {missing}")
print(f"Already have: {available}")
Expected Output:
Need to buy: ['butter', 'sugar']
Already have: ['eggs', 'flour', 'milk']
Problem 2: The Receipt Printer
Problem Statement: You are building a point-of-sale system. You have three lists representing a customer’s shopping cart. The lists are parallel (index 0 in all lists refers to the first item).
items: Names of products.prices: Base price of each product (float).quantities: How many of each product the customer is buying (int).
Write a script that iterates through these three lists simultaneously to generate a printed receipt.
Requirements:
- Use
zip()to group the data. - Use
enumerate()to generate line numbers starting at 1. - Calculate the total cost for each line (
price * quantity). - Print each line in the format:
Line #X: [Item Name] x[Qty] = $[Total] - At the end, print the Grand Total of the entire receipt.
Test Case:
items = ["Apple", "Banana", "Cherry"]
prices = [0.50, 0.30, 0.10]
quantities = [4, 2, 10]
# Write your loop here
Expected Output:
Line #1: Apple x4 = $2.0
Line #2: Banana x2 = $0.6
Line #3: Cherry x10 = $1.0
--------------------
Grand Total: $3.6
Problem 3: The Scholarship Committee
Problem Statement: You are writing a script to automatically select candidates for a university scholarship. You have three lists of data corresponding to the same students:
names: Student names (string).gpas: Grade Point Averages (float, 0.0 - 4.0).volunteering_hours: Total hours volunteered (int).
Rules for Eligibility: A student is eligible if they meet EITHER of these criteria:
- Academic Excellence: GPA is 3.8 or higher (regardless of volunteering).
- Well-Rounded: GPA is 3.5 or higher AND they have volunteered for more than 50 hours.
Your Task: Write a script that:
- Combines the lists into a single structure.
- Filters out the ineligible students based on the rules above.
- Sorts the eligible students by GPA in descending order. (If two students have the same GPA, sort them by volunteering hours descending).
- Returns/Prints a list of strings in the format:
"[Name]: [GPA] / [Hours]h".
Test Case:
names = ["Alice", "Bob", "Charlie", "David", "Eve"]
gpas = [3.9, 3.2, 3.6, 3.7, 3.5]
hours = [10, 100, 60, 20, 40]
# Alice: 3.9 (Eligible - Academic)
# Bob: 3.2 (Ineligible)
# Charlie: 3.6 + 60h (Eligible - Well Rounded)
# David: 3.7 + 20h (Ineligible - Needs 3.8 for Academic, or >50h for Well Rounded)
# Eve: 3.5 + 40h (Ineligible - Needs >50h)
Expected Output:
['Alice: 3.9 / 10h', 'Charlie: 3.6 / 60h']
Problem 4: The Hashtag Trend Analyzer
Problem Statement:
You are analyzing social media data to find trending topics. You have a list of raw tweet strings (tweets) and a set of “banned” hashtags (banned_tags) that should be ignored (e.g., generic tags like #fyp or #viral).
Your Task:
Write a function analyze_trends(tweets, banned_tags) that performs the following pipeline:
- Extract & Clean: Parse the tweets to find words starting with
#. Convert them to lowercase. - Filter: Remove any hashtags that are in the
banned_tagsset. - Count: Calculate the frequency of each remaining hashtag.
- Sort: Sort the hashtags by count (Highest to Lowest). If counts are equal, sort alphabetically (A-Z).
- Output: Return the top 3 trending hashtags as a list of tuples
(tag, count).
Constraints:
- Assume hashtags are separated by spaces in the strings.
- You must not count the banned tags.
Test Case:
tweets = [
"I love coding! #Python #coding #Life",
"Just learned #coding and lists in #PYTHON",
"#life is good but #coding is better",
"Ignore this #viral #FYP post"
]
banned = {"#viral", "#fyp"}
# Expected Logic:
# #python: 2
# #coding: 3
# #life: 2
# #viral, #fyp: Ignored
Expected Output:
[('#coding', 3), ('#life', 2), ('#python', 2)]
(Note: ‘#life’ and ‘#python’ both have 2, so ‘#life’ comes first alphabetically)
Problem 5: The Team Builder
Problem Statement:
You are organizing a Hackathon. You have a dictionary where the keys are team names and the values are lists of student IDs in that team.
teams = {"TeamA": [1, 2, 3], "TeamB": [3, 4, 5], "TeamC": [6, 7]}
However, there is a rule violation: A student cannot belong to more than one team.
Write a script that identifies:
- Disqualified Students: A set of IDs of students who are registered in more than one team.
- Valid Teams: A list of team names that have zero disqualified students.
- Total Unique Participants: The total headcount of distinct student IDs participating.
Requirements:
- You must find the students appearing in multiple lists dynamically (do not hardcode for just 3 teams).
- Use sets to efficiently track seen students and duplicates.
Test Case:
teams = {
"Alpha": [101, 102, 103],
"Beta": [103, 104, 105], # 103 is a duplicate (Alpha & Beta)
"Gamma": [106, 107], # Clean
"Delta": [102, 108] # 102 is a duplicate (Alpha & Delta)
}
Expected Output:
Disqualified Students: {102, 103}
Valid Teams: ['Gamma']
Total Unique Participants: 8
Problem 6: The Inventory Merger
Problem Statement:
You own two warehouses, warehouse_A and warehouse_B. Each is represented by a dictionary mapping Product_ID (string) to Quantity (int).
You need to merge these into a single total_inventory dictionary.
- If a product is in both warehouses, sum the quantities.
- If a product is only in one, keep its quantity.
- After merging, create a list of “Critical Stock” items: products with a total quantity less than 10.
Constraint: Try to iterate through the Union of keys from both dictionaries to solve this cleanly.
Test Case:
warehouse_A = {"apple": 5, "banana": 20, "orange": 3}
warehouse_B = {"apple": 2, "grape": 15, "orange": 4}
# Apple: 5 + 2 = 7 (Critical)
# Banana: 20 (OK)
# Orange: 3 + 4 = 7 (Critical)
# Grape: 15 (OK)
Expected Output:
Total Inventory: {'apple': 7, 'banana': 20, 'orange': 7, 'grape': 15}
Critical Stock: ['apple', 'orange']
This content will be available starting January 06, 2026.