AO
Back

Implement ToDo List for AI

Phone ScreenPhone ScreenLast reported April 2026Low Frequency

Problem Overview

Perplexity's "to-do list for AI" coding round, from two first-hand phone-screen reports (November 2025 and April 2026; one says the role was SWE). Both candidates were rejected the next day. Both say the problem has four parts, and both ran out of time after the second. A reply in the first thread adds another candidate who reached the third part.

The round reads like an OA: a long instruction sheet, and each part comes with its own test cases in a Python file you can read. One report says every part after the first has 6–7 test cases, and that each part includes a test that fails if earlier behaviour regresses, so change earlier code carefully. Python was required in one report. One interviewer started the problem straight away with no small talk; another, three months into the job, gave little help. One poster wondered who could finish all four parts in an hour; another candidate reached only the first two in 45 minutes.

Given — three classes

The reports name the classes TaskStatus (an Enum), Task and ToDoList, the statuses READY, BLOCKED, SUCCEEDED and FAILED, and the Part 1 methods add, get and update status. No starting code was captured, so the members and signatures below are this page's.

What the tests call (our setup — ask your interviewer)

class TaskStatus(Enum):
    READY = "READY"
    BLOCKED = "BLOCKED"
    SUCCEEDED = "SUCCEEDED"
    FAILED = "FAILED"

class Task:
    id: str
    status: TaskStatus

class ToDoList:
    def __init__(self): ...
    def add(self, task_id: str, dependencies: list[str] | None = None) -> Task: ...
    def get(self, task_id: str) -> Task: ...
    def update_status(self, task_id: str, new_status: TaskStatus) -> None: ...
    def serialize(self) -> str: ...  # Part 3

The tests read a task's id and status through get, and accept a status stored either as the enum member or as its string value. Every dependency in the tests is a task added earlier, so there are no unknown ids and no cycles.

Part 1 — Add, get, update status

Create a task, fetch it by id, and set its status. One candidate found this part not hard and advised getting through it fast. The tests never read a status before setting one, so the starting status in this part is yours to choose.

Part 2 — Dependencies and cascade

Each task now has dependencies: a list of the ids of tasks it depends on. Update add and update_status:

  • On add: if not every dependency has SUCCEEDED, the new task is BLOCKED. Otherwise it is READY (the reports state only the BLOCKED rule; READY is our reading).
  • On SUCCEEDED: the tasks this one was blocking update their status, for example from BLOCKED to READY. A task becomes READY only once all of its dependencies have succeeded, the add rule applied again.
  • On FAILED: every task that depends on the failed one fails, directly or through other tasks. The tasks it depends on, and unrelated tasks, keep their status.

So a task has to track both directions: its parents (the tasks it depends on) and its children (the tasks that depend on it). One candidate tracked only children at first and had to go back and change it. One report words both update rules with "dependencies"; the other says the failure reaches every task that depends on the failed one, and the tests grade that.

The reported wall is one large test. One candidate's DFS cascade passed every test but one very large one, which timed out and was still unfixed when the interview ended. They could not work out how that test was built and guessed a few hundred interdependent tasks. Our reading, not reported: a DFS with no visited guard walks a shared task once for every path that reaches it, which grows exponentially with depth when many tasks share dependencies. Failing each task once, and skipping tasks already FAILED, touches every task and edge at most once.

Our large test (our setup) builds layered graphs, each layer's tasks depending on every task in the layer before, from 10 to 40 layers plus a 200-task chain, and fails the first task. Each size (build, fail, read back) must finish within 1 second. The test stops at the first size over that, so a slow cascade fails in a few seconds instead of freezing the editor.

Part 3 — Serialize for an LLM

Put every task into one string. Any format is fine; the aim is that an LLM can understand it. One candidate wrote a topological sort and printed each task in that order; the report does not say how it was graded. Here serialize() returns the string, and printing it instead also passes (our setup). The tests check that every task id appears in the output and that serializing changes nothing: statuses stay the same, and later successes and failures still spread as before.

Not reported — the fourth part

No candidate in the reports reached the fourth part, so its content is unknown.

What Reports Emphasize

Interviewer hints: One interviewer started the problem straight away, with no small talk. Another, three months into the job, gave little help; one commenter felt the team was trying out a new question, so the interviewer could not help much.

What candidates did: Both counted candidates were rejected the next day. One finished Part 2 with two tests still failing. The other's DFS cascade passed every test but one very large one, which timed out. Another candidate, in a reply, printed the tasks in topological order for Part 3 and ran out of time before the fourth part; the report does not say how it was graded.

Common mistakes: tracking only one edge direction (one candidate tracked only children and had to go back); a cascade that revisits shared tasks, which is our reading of the reported timeout (its cause was not reported); promoting a task to READY when only some of its dependencies have succeeded (our analysis). Fix (ours): fail each task once and skip tasks already FAILED, so the cascade is O(V+E).

Practice

Write your own against 10 test cases, or read the worked solution — approach, complexity, and code that runs.
Perplexity · Phone Screen · Reported 2× across candidate reports
Is this helpful?