Exercises: Dictionaries and Sets
These exercises progress from basic dictionary operations through set mathematics to real-world data modeling. All code should run under Python 3.12+.
Difficulty Guide: - ⭐ Foundational (5-10 min each) - ⭐⭐ Intermediate (10-20 min each) - ⭐⭐⭐ Challenging (20-40 min each) - ⭐⭐⭐⭐ Advanced/Research (40+ min each)
Part A: Dictionary Basics ⭐
A.1. Create a dictionary called capitals that maps at least five countries to their capital cities. Then:
- Print the capital of one country using bracket notation
- Print the capital of a country that isn't in your dict using .get() with a default of "Unknown"
- Add a new country-capital pair
- Print the total number of countries in your dictionary
A.2. Given the following dictionary:
fruit_prices = {"apple": 1.20, "banana": 0.50, "cherry": 3.00, "date": 5.50}
Write code that:
- Prints the price of bananas
- Updates the price of cherries to 2.75
- Removes dates from the dictionary using pop() and prints the removed price
- Adds "elderberry" with a price of 4.25
A.3. What does each of the following expressions evaluate to? Predict first, then verify in the REPL.
info = {"name": "Alice", "age": 30, "city": "Portland"}
a = "name" in info
b = "Alice" in info
c = 30 in info
d = info.get("phone", "N/A")
e = len(info)
A.4. Explain the difference between del dict[key], dict.pop(key), and dict.pop(key, default). When would you use each one?
A.5. Fix the bugs in this code (there are three):
student = {"Name": "Bob", "grade" = "A", "gpa": 3.8}
print(student["name"])
student[[1, 2]] = "courses"
Part B: Iteration and Patterns ⭐⭐
B.1. Given a dictionary of students and their test scores:
scores = {
"Alice": [88, 92, 85, 91],
"Bob": [75, 80, 72, 68],
"Carol": [95, 98, 92, 97],
"Dave": [60, 55, 70, 65],
}
Write code that: - Calculates and prints each student's average score - Identifies the student with the highest average - Prints the names of students whose average is below 70
B.2. Write a function invert_dict(d) that takes a dictionary and returns a new dictionary with keys and values swapped. If two keys in the original have the same value, raise a ValueError with a helpful message. Test it with:
colors = {"red": "#FF0000", "green": "#00FF00", "blue": "#0000FF"}
grades = {"Alice": "A", "Bob": "B", "Carol": "A"} # Should raise ValueError
B.3. Write a function merge_inventories(inv1, inv2) that takes two inventory dictionaries (item name → quantity) and returns a single dictionary where quantities are summed for items that appear in both:
shop_a = {"sword": 3, "shield": 2, "potion": 10}
shop_b = {"shield": 1, "potion": 5, "bow": 4}
# Expected: {"sword": 3, "shield": 3, "potion": 15, "bow": 4}
B.4. Write a function word_frequency(text) that takes a string, converts it to lowercase, splits it into words, removes basic punctuation (periods, commas, exclamation marks, question marks), and returns a dictionary mapping each word to its frequency. Test it with:
text = "To be, or not to be, that is the question."
Expected: {'to': 2, 'be': 2, 'or': 1, 'not': 1, 'that': 1, 'is': 1, 'the': 1, 'question': 1}
B.5. Dr. Patel has multiple DNA sequences and wants to compare their nucleotide composition. Write a function nucleotide_profile(sequence) that returns a dictionary with the percentage of each nucleotide (A, T, G, C), rounded to one decimal place. Then compare two sequences:
seq1 = "ATGCGATCGATCGATCATGCATGC"
seq2 = "AAATTTGGGCCCAAATTTGGGCCC"
B.6. Write a function most_common_value(d) that takes a dictionary and returns the value that appears most frequently. If there's a tie, return any one of the tied values. Do NOT use Counter — build the frequency count manually.
Part C: Dictionary Comprehensions ⭐⭐
C.1. Using a dictionary comprehension, create a dictionary that maps numbers 1-10 to their cubes. Example: {1: 1, 2: 8, 3: 27, ...}
C.2. Given a dictionary of student scores:
scores = {"Alice": 92, "Bob": 67, "Carol": 88, "Dave": 45, "Eve": 73, "Frank": 91}
Use a dictionary comprehension to create: - A dict of only students who passed (score >= 70) - A dict mapping each student to their letter grade ("A" for 90+, "B" for 80-89, "C" for 70-79, "F" for below 70)
C.3. Given two lists of equal length:
keys = ["name", "age", "city", "language"]
values = ["Priya", 28, "Mumbai", "Python"]
Use zip() and a dictionary comprehension to create a dictionary from these two lists. Then do it again using the dict() constructor with zip() directly (no comprehension needed). Which is more readable?
C.4. Write a dictionary comprehension that takes a string and produces a dictionary of {character: ascii_value} for each unique character. Apply it to "Hello". (Hint: ord() gives the ASCII value of a character.)
Part D: Sets ⭐⭐
D.1. Given the following lists, use sets to answer each question:
cs_students = ["Alice", "Bob", "Carol", "Dave", "Eve"]
math_students = ["Bob", "Dave", "Frank", "Grace"]
physics_students = ["Carol", "Eve", "Frank", "Hank"]
- Who is enrolled in both CS and Math?
- Who is enrolled in CS but not Physics?
- Who is enrolled in all three courses?
- How many unique students are there across all three courses?
D.2. Write a function find_duplicates(items) that takes a list and returns a set of elements that appear more than once. Do NOT use Counter — use set logic.
find_duplicates([1, 2, 3, 2, 4, 3, 5]) # {2, 3}
find_duplicates(["a", "b", "c"]) # set()
D.3. A spell-checker compares words in a document against a dictionary of valid words. Write a function check_spelling(text, valid_words) where text is a string and valid_words is a set. Return a set of misspelled words (words in the text but not in the valid dictionary). Ignore case.
valid = {"the", "cat", "sat", "on", "mat", "a", "is", "and"}
text = "The cat sat on a rug and the dog barked"
# Expected: {"rug", "dog", "barked"}
D.4. Two friends compare their music libraries:
alice_songs = {"Bohemian Rhapsody", "Stairway to Heaven", "Hotel California",
"Imagine", "Smells Like Teen Spirit"}
bob_songs = {"Hotel California", "Imagine", "Yesterday",
"Like a Rolling Stone", "Bohemian Rhapsody"}
Write code to find: - Songs they can share with each other (songs only one of them has) - Songs they both already have - All unique songs between them
Part E: Integrated Challenges ⭐⭐⭐
E.1. Inventory Manager. Build a simple inventory system for the "Crypts of Pythonia" text adventure. Write functions:
- add_item(inventory, item, quantity=1) — add items (stack if already present)
- remove_item(inventory, item, quantity=1) — remove items (don't go below 0)
- has_item(inventory, item, min_quantity=1) — check if player has enough
- display_inventory(inventory) — formatted display
Test scenario:
inv = {}
add_item(inv, "torch", 3)
add_item(inv, "sword")
add_item(inv, "torch", 2) # Now has 5 torches
remove_item(inv, "torch", 2) # Now has 3 torches
print(has_item(inv, "torch", 5)) # False (only 3)
display_inventory(inv)
E.2. Grade Book. Create a grade book system using nested dictionaries:
gradebook = {
"Alice": {"homework": [90, 85, 92], "exams": [88, 92], "participation": 95},
"Bob": {"homework": [78, 80, 72], "exams": [75, 68], "participation": 85},
}
Write functions:
- calculate_final(student_record, hw_weight=0.4, exam_weight=0.5, part_weight=0.1) — weighted final grade
- class_average(gradebook) — overall class average
- top_student(gradebook) — name of highest-scoring student
E.3. Log Analyzer. Given a list of server log entries (as strings), build a function that returns a report dictionary:
logs = [
"2024-01-15 10:23:01 ERROR Database connection failed",
"2024-01-15 10:23:05 INFO Retrying connection",
"2024-01-15 10:23:06 INFO Connection established",
"2024-01-15 10:24:00 WARNING Disk usage at 85%",
"2024-01-15 10:25:30 ERROR Authentication failed",
"2024-01-15 10:25:31 INFO User logged out",
"2024-01-15 10:26:00 ERROR Database connection failed",
]
Your function should return:
{
"total_entries": 7,
"by_level": {"ERROR": 3, "INFO": 3, "WARNING": 1},
"unique_errors": {"Database connection failed", "Authentication failed"},
"error_rate": 42.9, # percentage, rounded to 1 decimal
}
E.4. Election Results. Process election data:
votes = ["Alice", "Bob", "Alice", "Carol", "Bob", "Alice",
"Carol", "Carol", "Bob", "Alice", "Carol", "Carol"]
Write a function election_results(votes) that returns a dictionary with:
- "counts": vote counts per candidate
- "winner": name of the winner
- "margin": difference between first and second place
- "total_votes": total number of votes cast
Part F: Advanced Challenges ⭐⭐⭐⭐
F.1. Two-Sum Problem. Given a list of integers and a target sum, find all pairs of numbers that add up to the target. Use a set for O(n) performance instead of the O(n²) brute-force approach with nested loops.
def two_sum(numbers, target):
"""Return a list of (a, b) tuples where a + b == target.
Each number can only be used once. a < b in each pair."""
pass # Your code here
print(two_sum([2, 7, 11, 15, 1, 8], 9))
# [(1, 8), (2, 7)]
F.2. Sparse Matrix. A sparse matrix has mostly zero values. Instead of storing all those zeros in a 2D list, use a dictionary with tuple keys (row, col) to store only non-zero values:
- set_value(matrix, row, col, value) — set a value (delete if zero)
- get_value(matrix, row, col) — get a value (default 0)
- add_matrices(m1, m2) — add two sparse matrices
- display_matrix(matrix, rows, cols) — pretty-print the full grid
F.3. Social Network Analysis. Model a social network as a dictionary where each person maps to a set of their friends:
network = {
"Alice": {"Bob", "Carol"},
"Bob": {"Alice", "Dave"},
"Carol": {"Alice", "Dave", "Eve"},
"Dave": {"Bob", "Carol"},
"Eve": {"Carol"},
}
Write functions:
- mutual_friends(network, person1, person2) — who are friends with both?
- friend_suggestions(network, person) — friends of friends who aren't already friends (and aren't the person themselves)
- most_connected(network) — person with the most friends