Chapter 5: Data Structures — Solutions
Worked solutions to the 50 Find the Bug exercises in Chapter 5: Data Structures. Each one names the kind of bug, explains why the original misbehaved, and shows the corrected program.
Solutions stay folded until you open them — try the exercise first; the diagnosis is where the learning is.
int
Solution 5.1.1 — Total points
Show the diagnosis and the fix
Bug type: Logical
The third section was subtracted instead of added, giving 25 instead of 75. Change the - to + so all three sections are summed.
section1 = 20
section2 = 30
section3 = 25
total = section1 + section2 + section3
print(total) # 75
Solution 5.1.2 — Students per team
Show the diagnosis and the fix
Bug type: Logical
The / operator always produces a float (6.0), but a whole number of students per team is wanted. Use integer division // to get the int 6.
students = 30
teams = 5
per_team = students // teams
print(per_team) # 6
Solution 5.1.3 — Seconds in an hour
Show the diagnosis and the fix
Bug type: Logical
The two counts must be multiplied, not added; 60 + 60 gives 120, not 3600. Use *.
seconds_per_minute = 60
minutes_per_hour = 60
seconds_per_hour = seconds_per_minute * minutes_per_hour
print(seconds_per_hour) # 3600
Solution 5.1.4 — Counting by tens
Show the diagnosis and the fix
Bug type: Runtime
"10" is a string, so count + "10" raises a TypeError (you cannot add an int and a str). Use the int literal 10.
count = 100
count = count + 10
print(count) # 110
Solution 5.1.5 — Apples per box
Show the diagnosis and the fix
Bug type: Logical
% gives the remainder (2 leftover apples), not the number of full boxes. Use integer division // to get 3.
apples = 17
per_box = 5
full_boxes = apples // per_box
print(full_boxes) # 3
float
Solution 5.2.1 — Average temperature
Show the diagnosis and the fix
Bug type: Logical
Without parentheses, only reading3 / 3 is divided (operator precedence), so the sum is wrong. Wrap the addition in parentheses before dividing.
reading1 = 20.0
reading2 = 22.0
reading3 = 24.0
average = (reading1 + reading2 + reading3) / 3
print(average) # 22.0
Solution 5.2.2 — Splitting a bill
Show the diagnosis and the fix
Bug type: Logical
// discards the fractional part, giving 12 instead of 12.5. Use true division / so the result is a float.
bill = 50
people = 4
each = bill / people
print(each) # 12.5
Solution 5.2.3 — Rounding a price
Show the diagnosis and the fix
Bug type: Logical
round(price) with no second argument rounds to a whole number (3). Pass 2 to round to two decimal places.
price = 3.14159
rounded = round(price, 2)
print(rounded) # 3.14
Solution 5.2.4 — Half of a measurement
Show the diagnosis and the fix
Bug type: Syntax
The closing parenthesis of print(...) is missing, so the program will not parse. Add the ) after half.
length = 9.0
half = length / 2
print(half) # 4.5
Solution 5.2.5 — Celsius to Fahrenheit
Show the diagnosis and the fix
Bug type: Logical
Operator precedence makes celsius * 9 / 5 - 32 subtract 32 instead of adding it, and the +32 must come after the multiply/divide. Add parentheses or use + 32: the formula is celsius * 9 / 5 + 32.
celsius = 100.0
fahrenheit = celsius * 9 / 5 + 32
print(fahrenheit) # 212.0
bool
Solution 5.3.1 — Is it freezing?
Show the diagnosis and the fix
Bug type: Logical
“Below freezing” means less than 0, but the test used >, which is False for -5. Use < so the comparison returns True.
temp = -5
is_freezing = temp < 0
print(is_freezing) # True
Solution 5.3.2 — Passing grade
Show the diagnosis and the fix
Bug type: Runtime
Passed (capital P) is a different, undefined name, so printing it raises a NameError. Print the variable passed.
grade = 72
passed = grade >= 60
print(passed) # True
Solution 5.3.3 — Both lights on
Show the diagnosis and the fix
Bug type: Logical
“Both” requires and; or is True when either light is on. Use and so the result is False here.
light1_on = True
light2_on = False
ready = light1_on and light2_on
print(ready) # False
Solution 5.3.4 — Empty cart
Show the diagnosis and the fix
Bug type: Logical
is_empty = items = 0 is a chained assignment that sets is_empty to 0, not the comparison you intended; it runs but prints 0. Comparing values needs ==, so write is_empty = items == 0.
items = 0
is_empty = items == 0
print(is_empty) # True
Solution 5.3.5 — Within speed limit
Show the diagnosis and the fix
Bug type: Logical
Being within the limit means the speed is at or below it, but > tests the opposite. Use <= so 60 within 65 gives True.
speed = 60
limit = 65
within_limit = speed <= limit
print(within_limit) # True
Strings
Solution 5.4.1 — First letter
Show the diagnosis and the fix
Bug type: Logical
String indexing starts at 0, so city[1] is the second letter (“o”). Use index 0 for the first letter.
city = "Tokyo"
first = city[0]
print(first) # T
Solution 5.4.2 — Shouting
Show the diagnosis and the fix
Bug type: Logical
word.upper refers to the method without calling it, so it prints a method object, not the text. Add parentheses to call it: word.upper().
word = "hello"
loud = word.upper()
print(loud) # HELLO
Solution 5.4.3 — Full name
Show the diagnosis and the fix
Bug type: Logical
Concatenation does not insert a space, so the result is “MayaSingh”. Add a space string between the names.
first = "Maya"
last = "Singh"
full = first + " " + last
print(full) # Maya Singh
Solution 5.4.4 — Length of a word
Show the diagnosis and the fix
Bug type: Runtime
word() tries to call the string as if it were a function, raising a TypeError. Pass the string itself to len.
word = "science"
count = len(word)
print(count) # 7
Solution 5.4.5 — Last three characters
Show the diagnosis and the fix
Bug type: Logical
code[-3] is a single character (“7”), not the last three. Slice with code[-3:] to get “789”.
code = "ABC789"
last_three = code[-3:]
print(last_three) # 789
None
Solution 5.5.1 — No reading yet
Show the diagnosis and the fix
Bug type: Logical
None is not the same as the string "None", so the comparison is always False. Compare to the real None value with is None.
reading = None
no_data = reading is None
print(no_data) # True
Solution 5.5.2 — Default color
Show the diagnosis and the fix
Bug type: Logical
The function changes color but never returns it, so it returns None. Add a return color statement.
def choose_color(color):
if color is None:
color = "blue"
return color
print(choose_color(None)) # blue
Solution 5.5.3 — Checking for a value
Show the diagnosis and the fix
Bug type: Logical
The test is not None is False when the value is None, so the program runs the wrong branch and prints “has value”. Use is None so a None value prints “missing”.
favorite = None
if favorite is None:
print("missing")
else:
print("has value")
# expected: missing
Solution 5.5.4 — Length of nothing
Show the diagnosis and the fix
Bug type: Runtime
len(None) raises a TypeError because None has no length. Check for None first and use 0 in that case.
temps = None
count = len(temps) if temps is not None else 0
print(count) # 0
Solution 5.5.5 — Comparing to None
Show the diagnosis and the fix
Bug type: Runtime
Not_set (capital N) is undefined, so printing it raises a NameError. Print the variable not_set.
username = None
not_set = username is None
print(not_set) # True
Lists
Solution 5.6.1 — First fruit
Show the diagnosis and the fix
Bug type: Logical
List indexing starts at 0, so fruits[1] is “banana”. Use index 0 for the first fruit.
fruits = ["apple", "banana", "orange"]
print(fruits[0]) # apple
Solution 5.6.2 — Adding an item
Show the diagnosis and the fix
Bug type: Runtime
Lists have no add method, so this raises an AttributeError. Use append to add to a list.
fruits = ["apple", "banana", "orange"]
fruits.append("grape")
print(len(fruits)) # 4
Solution 5.6.3 — Last score
Show the diagnosis and the fix
Bug type: Runtime
The list has indexes 0, 1, 2, so scores[3] is out of range and raises an IndexError. The last item is at index 2 (or use -1).
scores = [70, 95, 88]
print(scores[-1]) # 88
Solution 5.6.4 — Changing a value
Show the diagnosis and the fix
Bug type: Syntax
Item assignment uses square brackets, not parentheses; prices(1) = 5.0 is not valid Python. Use prices[1] = 5.0.
prices = [2.0, 3.0, 4.0]
prices[1] = 5.0
print(prices) # [2.0, 5.0, 4.0]
Solution 5.6.5 — How many items
Show the diagnosis and the fix
Bug type: Logical
len(shopping) already gives 3; subtracting 1 makes it 2. Remove the - 1.
shopping = ["milk", "eggs", "bread"]
count = len(shopping)
print(count) # 3
Tuples
Solution 5.7.1 — Map coordinates
Show the diagnosis and the fix
Bug type: Logical
Index 0 is the latitude; location[1] returns the longitude. Use index 0.
location = (41.8781, -87.6298)
print(location[0]) # 41.8781
Solution 5.7.2 — A fixed pair
Show the diagnosis and the fix
Bug type: Runtime
Tuples are immutable, so size[0] = 1280 raises a TypeError. You cannot change one element in place; build a new tuple instead.
size = (1920, 1080)
size = (1280, size[1])
print(size) # (1280, 1080)
Solution 5.7.3 — Unpacking coordinates
Show the diagnosis and the fix
Bug type: Logical
Assigning the whole tuple to each name does not unpack it. Unpack both values at once with lat, lon = coords.
coords = (35.7, 139.7)
lat, lon = coords
print(f"lat {lat}, lon {lon}") # lat 35.7, lon 139.7
Solution 5.7.4 — A single value
Show the diagnosis and the fix
Bug type: Runtime
(42) is just the number 42 in parentheses, not a tuple, so len(single) raises a TypeError on an int. A one-element tuple needs a trailing comma: (42,).
single = (42,)
print(len(single)) # 1
Solution 5.7.5 — Days in a tuple
Show the diagnosis and the fix
Bug type: Logical
Index 1 is the second item (“Tue”); days[2] returns “Wed”. Use index 1.
days = ("Mon", "Tue", "Wed")
print(days[1]) # Tue
Sets
Solution 5.8.1 — Unique colors
Show the diagnosis and the fix
Bug type: Logical
Square brackets create a list, which keeps the duplicate “red”, so len is 4. Use curly braces to make a set, which drops duplicates and gives 3.
colors = {"red", "blue", "red", "green"}
print(len(colors)) # 3
Solution 5.8.2 — Adding a member
Show the diagnosis and the fix
Bug type: Runtime
Sets have no append method, so this raises an AttributeError. Use add to put an item in a set.
cities = {"New York", "London", "Tokyo"}
cities.add("Sydney")
print(len(cities)) # 4
Solution 5.8.3 — Is it a member?
Show the diagnosis and the fix
Bug type: Logical
The program tests “yellow”, which is not in the set, so it prints False. Test for “blue” to get True.
colors = {"red", "blue", "green"}
print("blue" in colors) # True
Solution 5.8.4 — Shared subjects
Show the diagnosis and the fix
Bug type: Logical
| is union (all subjects from both); shared items need intersection &. Use maya & leo to get just {"math"}.
maya = {"math", "science", "art"}
leo = {"math", "history"}
shared = maya & leo
print(shared) # {'math'}
Solution 5.8.5 — Building a set
Show the diagnosis and the fix
Bug type: Runtime
{} creates an empty dictionary, not a set, so seen.add raises an AttributeError. Use set() to create an empty set.
seen = set()
seen.add("apple")
print(seen) # {'apple'}
Dictionaries
Solution 5.9.1 — Looking up a name
Show the diagnosis and the fix
Bug type: Runtime
Keys are case-sensitive; "Name" is not in the dict, so this raises a KeyError. Use the actual key "name".
student = {"name": "Maya", "grade": 10}
print(student["name"]) # Maya
Solution 5.9.2 — Updating a grade
Show the diagnosis and the fix
Bug type: Syntax
Dictionary assignment uses square brackets, not parentheses; student("grade") = 11 is invalid. Use student["grade"] = 11.
student = {"name": "Maya", "grade": 10}
student["grade"] = 11
print(student["grade"]) # 11
Solution 5.9.3 — Missing key
Show the diagnosis and the fix
Bug type: Runtime
Indexing a missing key with [] raises a KeyError. Use .get with a default so it returns “not found” instead.
student = {"name": "Maya", "grade": 10}
subject = student.get("favorite_subject", "not found")
print(subject) # not found
Solution 5.9.4 — Safe default with get
Show the diagnosis and the fix
Bug type: Runtime
Subject (capital S) is undefined, so printing it raises a NameError. Print the variable subject.
student = {"favorite_subject": "science"}
subject = student.get("favorite_subject", "unknown")
print(subject) # science
Solution 5.9.5 — Adding an entry
Show the diagnosis and the fix
Bug type: Runtime
== compares values; it does not store anything, so the key “phone” is never added and the next line raises a KeyError. Use a single = to assign the new entry.
contact = {"name": "Leo"}
contact["phone"] = "555-0100"
print(contact["phone"]) # 555-0100
Variables and Types
Solution 5.10.1 — Reading a number
Show the diagnosis and the fix
Bug type: Runtime
age_text is a string, so age_text + 5 mixes str and int and raises a TypeError. Convert the text with int() before adding.
age_text = "25"
age = int(age_text) + 5
print(age) # 30
Solution 5.10.2 — Building a message
Show the diagnosis and the fix
Bug type: Runtime
You cannot concatenate a str and an int, so this raises a TypeError. Convert the number with str() first.
score = 90
message = "Score: " + str(score)
print(message) # Score: 90
Solution 5.10.3 — Checking a type
Show the diagnosis and the fix
Bug type: Logical
The price is a float, but the check compares against int, so it reports False. Compare against float.
price = 3.99
print(type(price)) # <class 'float'>
print(type(price) == float) # True
Solution 5.10.4 — Converting to float
Show the diagnosis and the fix
Bug type: Runtime
int("2.5") raises a ValueError because the text is not a whole number. Use float() to convert it.
weight_text = "2.5"
weight = float(weight_text)
print(weight * 2) # 5.0
Solution 5.10.5 — Whole-number average
Show the diagnosis and the fix
Bug type: Runtime
average is wrapped in str(), so int("85.5") raises a ValueError. Keep the average numeric and apply int() directly.
score1 = 80
score2 = 91
average = (score1 + score2) / 2
print(int(average)) # 85