The Social Graph
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
- L3
- Asked in
- Meta
Problem
You're filling the friend-count column from a social graph export, where each record is either a pair of names, meaning those two people are mutual friends, or a single name, meaning a person who has shown up with no connections. Return a mapping from every person who appears to how many friends they have, where each pair adds one to both of its names and anyone who only ever appears alone lands at 0.
Everyone knows someone.
Example
Input:
groups = [["Ana","Ben"],["Ana","Cleo"],["Ben","Dan"],["Ben","Cleo"],["Ray","Mia"],["Sam"],["Pat"],["Ana"]]
Output:
{"Ana":2,"Ben":3,"Cleo":2,"Dan":1,"Ray":1,"Mia":1,"Sam":0,"Pat":0}Worked solution and explanation
What this really is
Strip the friend-group costume off and this is a degree count over an undirected edge list, plus one initialization gotcha. Anyone can bump two counters per pair. What actually separates candidates is remembering that a name's FIRST appearance is what puts it in the dict at all. A person who only ever shows up alone, or as the silent second name in a pair, has to be seeded at 0 before any increment. Miss that and isolated people vanish from the output entirely, which is exactly the case an interviewer is checking.
The two cases
Step 1: Seed every name you see at 0
Loop the names in each group and setdefault each one to 0. This single line is what guarantees singletons and second-in-pair names actually exist as keys before you ever touch a counter.
Step 2: A two-name group is one bidirectional friendship
If the group has two names, add one to each. Undirected means both endpoints gain a friend, not just the first name listed.
Step 3: Return the map
The keys are everyone who appeared; the values are their friend totals. Singletons and pair members are already present from step 1.
The solution
def count_friends(groups: list[list[str]]) -> dict[str, int]:
friends: dict[str, int] = {}
for group in groups:
for person in group:
friends.setdefault(person, 0)
if len(group) == 2:
a, b = group
friends[a] += 1
friends[b] += 1
return friendsSeeding every name first is what folds the singleton case into the same loop as the pairs.
- Only counts pairs
- Iterating just the len == 2 groups and bumping counters never creates a key for [Sam] or [Pat]. They disappear, and Dan, who only appears as a second name, is fine only because the increment creates him by luck.
- Seeds then counts
- The setdefault pass creates a 0 entry for every name on sight, so a lone person and a second-name-in-a-pair both exist before any math. The increment then just adds to keys that are guaranteed present.
Common follow-up questions
- What if a group could have more than two people who are all mutual friends? (Tests generating all pairwise friendships within a group.)
- How would you find connected components of the friend graph? (Tests BFS/DFS traversal on the adjacency structure.)
- What if the same pair could appear multiple times in the input? (Tests deduplicating before counting.)