Python, Concept by Concept › Dictionaries
Exercises: Dictionaries
Core work is Exercises 1–10. Exercises 11–24 are More Practice; Exercises 25–28 are optional Challenges. Define each requested function, return the promised value, and try every worked sample call.
Keep each exact function name and parameter list. Build dictionaries with literals or loop assignment, never a comprehension. Add a short purpose comment and use meaningful names. The calls supply every input; each Real version reads the same values with input().
Exercise 1: Planet Day Lookup
A space club needs a small lookup table for the length of a day in whole Earth hours.
Specification: Define day_hours(planet). Inside the function, make the dictionary {'Mercury': 4223, 'Earth': 24, 'Mars': 25}. Return the value stored at key planet with square-bracket access. Each sample uses a key that exists.
Worked sample calls:
day_hours("Earth") -> 24
day_hours("Mars") -> 25
day_hours("Mercury") -> 4223
Real program
The real program reads one planet name with input().
How this is checked: Checked by tests that run your function day_hours.
Exercise 2: Safe Snack Count
A snack table should report zero when a requested snack is missing.
Specification: Define snack_count(snacks, name). Return snacks.get(name, 0). Do not change the input dictionary.
Worked sample calls:
snack_count({"apple": 5, "cracker": 8}, "apple") -> 5
snack_count({"apple": 5, "cracker": 8}, "banana") -> 0
snack_count({}, "cracker") -> 0
Real program
The real program reads a snack count and that many snack amount lines, then a requested snack with input().
How this is checked: Checked by tests that run your function snack_count.
Exercise 3: Supply Total
A classroom manager needs the total number of supplies across every labelled bin.
Specification: Define total_supplies(supplies). Start total at 0. Loop with for item, amount in supplies.items(): and add each integer amount to total. Return the final total. The two loop names receive one key/value pair per trip.
Worked sample calls:
total_supplies({"pens": 9, "paper": 20, "tape": 2}) -> 31
total_supplies({"clips": 7}) -> 7
total_supplies({}) -> 0
Real program
The real program reads a supply count and that many item amount lines with input().
How this is checked: Checked by tests that run your function total_supplies.
Exercise 4: Busiest Station
A transit map stores the rider count for each station.
Specification: Define busiest_station(riders) for a non-empty dictionary of non-negative integer counts. Start best_station = "" and best_count = -1. Loop over riders.items(). Replace both best values only when the current count is strictly greater than best_count. Return the winning station. If counts tie, the first tied key wins. Do not call max for this exercise.
Worked sample calls:
busiest_station({"Oak": 12, "Pine": 19, "Elm": 8}) -> "Pine"
busiest_station({"North": 4}) -> "North"
busiest_station({"Red": 7, "Blue": 7, "Gold": 3}) -> "Red"
Real program
The real program reads a station count and that many station riders lines with input().
How this is checked: Checked by tests that run your function busiest_station.
Exercise 5: Case-Folding Word Tally
A word game wants "Cloud" and "cloud" to count as the same word.
Specification: Define word_counts(words). Start with an empty dictionary. For each word, set key = word.lower(). Use the primary missing-key pattern: when key in counts, assign counts[key] = counts[key] + 1; otherwise assign counts[key] = 1. Return the completed dictionary.
Worked sample calls:
word_counts(["Cloud", "rain", "cloud"]) -> {'cloud': 2, 'rain': 1}
word_counts(["GO", "go", "Go", "stop"]) -> {'go': 3, 'stop': 1}
word_counts([]) -> {}
Real program
The real program reads words on one line with input().
How this is checked: Checked by tests that run your function word_counts.
Exercise 6: First-Letter Shelves
A librarian groups non-empty words by their first letter while keeping the original order within each group.
Specification: Define shelve_by_first(words). Start with an empty dictionary. For each word, use letter = word[0]. Build each list value with exactly this explicit form:
if letter in shelves:
shelves[letter].append(word)
else:
shelves[letter] = [word]
Return shelves. Do not use get for this grouping job.
Worked sample calls:
shelve_by_first(["cat", "crow", "dog", "camel"]) -> {'c': ['cat', 'crow', 'camel'], 'd': ['dog']}
shelve_by_first(["sun", "moon", "star"]) -> {'s': ['sun', 'star'], 'm': ['moon']}
shelve_by_first([]) -> {}
Real program
The real program reads words on one line with input().
How this is checked: Checked by tests that run your function shelve_by_first.
Exercise 7: Sorted Score Board
A game host wants a leaderboard ordered from the lowest score to the highest.
Specification: Define score_board(scores). Start board as an empty list. Loop over scores.items() and append [score, name] for each pair. Call board.sort() with no arguments, then return board. The sample scores are unique.
Worked sample calls:
score_board({"Mia": 14, "Leo": 9, "Zoe": 18}) -> [[9, 'Leo'], [14, 'Mia'], [18, 'Zoe']]
score_board({"Ivy": 3, "Kai": 11}) -> [[3, 'Ivy'], [11, 'Kai']]
score_board({}) -> []
Real program
The real program reads a player count and that many name score lines with input().
How this is checked: Checked by tests that run your function score_board.
Exercise 8: Morse Encoder
A signal desk turns letters into Morse code.
Specification: Define to_morse(message). Add a purpose comment. Use this given table: {"A": ".-", "E": ".", "N": "-.", "O": "---", "S": "...", "T": "-"}. For each uppercase letter, append its code to a list. Return " ".join(codes).
Worked sample calls:
to_morse("NOTE") -> "-. --- - ."
to_morse("SOS") -> "... --- ..."
Real program
The real program reads one uppercase message with input().
How this is checked: Checked by tests that run your function to_morse.
Exercise 9: Roman Numeral Value
A history display converts Roman numerals into whole numbers.
Specification: Define roman_to_int(s). Add a purpose comment. Use {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100}. Visit each position by index. If its value is smaller than the next symbol’s value, subtract it; otherwise add it. The last symbol is added. Return the total. Use an if/elif/else chain to distinguish a smaller next value, the last position, and an ordinary addition.
Worked sample calls:
roman_to_int("XLII") -> 42
roman_to_int("LXIX") -> 69
Real program
The real program reads one Roman numeral with input().
How this is checked: Checked by tests that run your function roman_to_int.
Exercise 10: Letter Tally Chart
A word artist turns letter counts into bars.
Specification: Define tally_chart(word). Add a purpose comment. Count each letter in a dictionary. Visit its keys in first-appearance order and append each row as f"{ch} " + "#" * count to a list. Return "\n".join(rows); no trailing spaces.
Worked sample calls:
tally_chart("papaya") -> "p ##\na ###\ny #"
Real program
The real program reads one lowercase word with input().
How this is checked: Checked by tests that run your function tally_chart.
Exercise 11: More Practice: Invert a Dictionary
A decoder needs labels for short codes.
Specification: Define invert(mapping). The input values are unique. Loop over mapping.items() and assign each old value as a new key with the old key as its value. Return the new dictionary.
Worked sample calls:
invert({"cold": "C", "warm": "W", "hot": "H"}) -> {'C': 'cold', 'W': 'warm', 'H': 'hot'}
Real program
The real program reads a count, then that many word code lines with input().
How this is checked: Checked by tests that run your function invert.
Exercise 12: More Practice: Anagram by Tally
A word puzzle compares letter supplies.
Specification: Define is_anagram(first, second). Build a separate letter-count dictionary for each word, then compare the dictionaries with ==. Use the same tally method on both words; return the Boolean result.
Worked sample calls:
is_anagram("listen", "silent") -> True
is_anagram("cider", "crumb") -> False
Real program
The real program reads two words on separate lines with input().
How this is checked: Checked by tests that run your function is_anagram.
Exercise 13: More Practice: Price Lookup Total
A checkout table adds item prices, including repeated purchases.
Specification: Define cart_total(prices, items). Start a total at zero; for each item in the list, add prices[item]. Return the total. All listed items have a price.
Worked sample calls:
cart_total({"pen": 3, "pad": 5, "ink": 12}, ["pen", "ink", "pen"]) -> 18
Real program
The real program reads a count and that many item price lines, then item names on one line with input().
How this is checked: Checked by tests that run your function cart_total.
Exercise 14: More Practice: Luhn Check Digit
A check digit flags a mistyped number.
Specification: Define luhn_valid(s). Scan the digit string from right to left using s[len(s) - 1 - i]. Convert each digit with int. Double every second digit from the right (positions 1, 3, ...); if a doubled value exceeds 9, subtract 9. Add values to a total and return whether total % 10 == 0. Do not use a negative slice step.
Worked sample calls:
luhn_valid("79927398713") -> True
luhn_valid("79927398710") -> False
Real program
The real program reads one check-digit string with input().
How this is checked: Checked by tests that run your function luhn_valid.
Exercise 15: More Practice: Scores from Records
Several records may update the same player total.
Specification: Define parse_records(records). Each string is name score. Split each record and convert parts[1] with int. If the name already exists, add the score to its stored total; otherwise store the first score. Return the dictionary.
Worked sample calls:
parse_records(["Rin 12", "Oto 7", "Rin 5"]) -> {'Rin': 17, 'Oto': 7}
Real program
The real program reads a record count, then that many name score lines with input().
How this is checked: Checked by tests that run your function parse_records.
Exercise 16: More Practice: Group by Length
A word shelf groups words of equal length.
Specification: Define group_by_length(words). Use word lengths as dictionary keys and lists of words as values. For each word, use an explicit membership test: append to an existing group, or assign [word] to a new group. Keep word order.
Worked sample calls:
group_by_length(["elk", "ibex", "yak", "hare", "gnu"]) -> {3: ['elk', 'yak', 'gnu'], 4: ['ibex', 'hare']}
Real program
The real program reads words on one line with input().
How this is checked: Checked by tests that run your function group_by_length.
Exercise 17: More Practice: Most Frequent Letter
A typesetter needs the most common letter.
Specification: Define top_letter(word) for a non-empty word with one unique most frequent letter. Tally its letters with a conditional increment, then scan the pairs with a strict > comparison to keep the leader. Return its letter.
Worked sample calls:
top_letter("bookkeeper") -> "e"
Real program
The real program reads one lowercase word with input().
How this is checked: Checked by tests that run your function top_letter.
Exercise 18: More Practice: Vote Percentages
A poll report converts counts into percentages.
Specification: Define percentages(votes) for a non-empty dictionary with a positive total. First total all counts with a loop. Then build a new dictionary whose value for each key is count / total * 100. Return it.
Worked sample calls:
percentages({"yes": 6, "no": 2}) -> {'yes': 75.0, 'no': 25.0}
Real program
The real program reads a count, then that many choice votes lines with input().
How this is checked: Checked by tests that run your function percentages.
Exercise 19: More Practice: Word Translator
A pocket glossary changes known words and keeps unknown ones.
Specification: Define translate(line, dictionary). Split the line into words. For each word, append dictionary.get(word, word) to a result list. Return " ".join(result).
Worked sample calls:
translate("a red hen", {"red": "rojo", "hen": "gallina"}) -> "a rojo gallina"
Real program
The real program reads a glossary count and that many word translation lines, then one sentence with input().
How this is checked: Checked by tests that run your function translate.
Exercise 20: More Practice: Fix the KeyError
A stock report asks for an absent key.
Specification: The broken code is:
stock = {"nails": 40}
print(stock["screws"])
KeyError: 'screws'
Define safe_stock(stock, name) to return stock.get(name, 0). Use it to repair the printed lookup without changing the dictionary.
Worked sample calls:
safe_stock({"nails": 40}, "screws") -> 0
print(safe_stock({"nails": 40}, "screws")) -> 0
How this is checked: Checked by tests that run your function safe_stock.
Exercise 21: More Practice: Predict the Update
Trace what two assignments do to a dictionary.
Specification: Predict the output of this code, then define updated_dict() that performs the same assignments and returns the dictionary:
d = {"a": 1}
d["a"] = d["a"] + 5
d["b"] = 2
print(d)
This code runs without an error — predict what it prints.
Worked sample calls:
updated_dict() -> {'a': 6, 'b': 2}
print(updated_dict()) -> {'a': 6, 'b': 2}
Starter (read-only)
# Define updated_dict(), then try all sample calls.How this is checked: Checked by comparing your prediction with what the program really prints.
Answer format: one line
Exercise 22: More Practice: Alphabetical Keys
A catalog prints its labels alphabetically.
Specification: Define sorted_keys(mapping). Append every key to a list, call .sort() on that list with no arguments, and return it. Do not call sorted(mapping).
Worked sample calls:
sorted_keys({"quince": 4, "lime": 9, "date": 2}) -> ['date', 'lime', 'quince']
Real program
The real program reads a count, then that many word number lines with input().
How this is checked: Checked by tests that run your function sorted_keys.
Exercise 23: More Practice: Low Stock
A supply list selects items below a cutoff.
Specification: Define low_stock(stock, limit). Loop through keys in dictionary order, append each key whose value is less than limit, and return the list.
Worked sample calls:
low_stock({"bolts": 3, "gears": 12, "springs": 1}, 5) -> ['bolts', 'springs']
Real program
The real program reads a count and that many item amount lines, then a limit with input().
How this is checked: Checked by tests that run your function low_stock.
Exercise 24: More Practice: Missing Prices
A cashier needs names absent from a price table.
Specification: Define missing_prices(prices, items). Visit items in list order; append an item when it is not in the price dictionary. Return the list.
Worked sample calls:
missing_prices({"pen": 3, "pad": 5}, ["pad", "cap", "pen", "mug"]) -> ['cap', 'mug']
Real program
The real program reads a price count and that many item price lines, then item names on one line with input().
How this is checked: Checked by tests that run your function missing_prices.
Exercise 25: Qualifying Players
A tournament needs the names whose scores meet a cutoff.
Specification: Define qualifiers(scores, minimum). Start an empty list named passing. Loop over scores.items(). If a score is at least minimum, append its name to passing. Return the list. Keep the dictionary's visit order.
Worked sample calls:
qualifiers({"Ana": 16, "Bo": 7, "Cy": 12}, 10) -> ['Ana', 'Cy']
qualifiers({"Dee": 5, "Eli": 6}, 6) -> ['Eli']
qualifiers({"Fox": 4}, 9) -> []
Real program
The real program reads a player count and that many name score lines, then the minimum score with input().
How this is checked: Checked by tests that run your function qualifiers.
Exercise 26: Word Winner Report
A headline tool needs both a case-insensitive tally and its most common word.
Specification: Define word_winner(words) for a non-empty list with one unique most-common lowercase word. First build counts with a loop. This time use the shortcut assignment counts[key] = counts.get(key, 0) + 1 after setting key = word.lower(). Then use a separate strict find-extreme loop over counts.items(). Return an f-string in the form "word: count".
Worked sample calls:
word_winner(["Red", "blue", "red"]) -> "red: 2"
word_winner(["owl", "fox", "FOX", "fox"]) -> "fox: 3"
word_winner(["solo"]) -> "solo: 1"
Real program
The real program reads words on one line with input().
How this is checked: Checked by tests that run your function word_winner.
Exercise 27: Morse Decoder
A receiver turns separated Morse codes into letters.
Specification: Define from_morse(message). Use the same given code table as Morse Encoder: {"A": ".-", "E": ".", "N": "-.", "O": "---", "S": "...", "T": "-"}. Invert the table with a loop. Split the Morse message on spaces, look up each code, and build the returned word.
Worked sample calls:
from_morse("- . -.") -> "TEN"
Real program
The real program reads one space-separated Morse message with input().
How this is checked: Checked by tests that run your function from_morse.
Exercise 28: Report Card
A report card shows averages in name order.
Specification: Define report_card(scores) where each name maps to a non-empty list of scores. Collect names into a list and call .sort(). For each name, compute its average and append the row f"{name} {average}". Return "\n".join(rows) with no trailing spaces.
Worked sample calls:
report_card({"Pax": [70, 75, 80], "Juno": [90, 80]}) -> "Juno 85.0\nPax 75.0"
Real program
The real program reads a name count, then each name on one line followed by its score count and scores on one line with input().
How this is checked: Checked by tests that run your function report_card.