The Word Map
An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- easy
- Seniority
- L4
- Asked in
- phData
Problem
We're building a keyword index over a batch of user-submitted text, and the first pass just needs raw word counts. Return a dict mapping each word to how many times it appears, comparing words case-insensitively and ignoring any punctuation stuck to the outer edges of a word.
Language, quantified.
Example 1
Input:
text = "the cat and the dog"
Output:
{"the":2,"cat":1,"and":1,"dog":1}Example 2
Input:
text = "Hello, hello! HELLO."
Output:
{"hello":3}Worked solution and explanation
What this really tests
Underneath the keyword-index framing, this is a normalize-then-tally: can you fold every surface form of a word ('The', 'the', 'the,') onto one canonical key before you count? Anyone can split on whitespace and bump a dict. The catch is doing the normalization FIRST: lowercase the token and peel the punctuation off its edges, so 'cat' and 'cat,' hit the same bucket. Skip that and you count 'The' and 'the' as two different words, and every frequency in your map is quietly wrong.
The build, step by step
Step 1: Normalize case up front
Call text.lower() on the whole string once, before you split. Fold case at the source and 'HELLO', 'Hello', and 'hello' become one key for free. Lowercasing per-token later works too, but it invites the bug where one branch forgets to do it.
Step 2: Strip only the outer punctuation
For each token, token.strip(string.punctuation) shaves leading and trailing marks ('cat,' becomes 'cat', 'wait...' becomes 'wait') while leaving anything interior alone. That last part is deliberate: 'don't' keeps its apostrophe and stays one word, which is exactly why edge-stripping beats deleting every punctuation character.
Step 3: Tally with dict.get
Accumulate into a plain dict: counts[word] = counts.get(word, 0) + 1. One pass, O(n), and the default-of-zero pattern means you never special-case the first sighting of a word. Guard against the empty string so a token that was pure punctuation doesn't create a '' key.
The solution
import string
def the_word_map(text):
counts = {}
for token in text.lower().split():
word = token.strip(string.punctuation)
if not word:
continue
counts[word] = counts.get(word, 0) + 1
return counts- Manual dict.get
- Explicit and dependency-free:
counts.get(word, 0) + 1reads as exactly what it does, and it is the version to reach for when the interviewer wants to watch you handle the accumulation by hand. - collections.Counter
Counter(words)is the idiomatic one-liner and hands youmost_common(k)for the follow-up. Same O(n). Cast todictif the contract insists on a plain dict. Reach for it once you have shown you know what it is doing underneath.
Common follow-up questions
- How would you return only the 5 most frequent words? (Reach for Counter(words).most_common(5). Shows you do not need to sort the entire dict to answer top-k.)
- How would you count words across a 50 GB file that does not fit in memory? (Iterate line by line and feed each tokenized batch into a single persistent counter. Discuss the memory bound: it scales with vocabulary, not corpus size.)
- How would you make 'don't' and 'dont' count as the same word? (Decide the policy explicitly: strip apostrophes before tallying, or keep them and normalize afterward. Surface the tradeoff with possessives like 'Alice's'.)