Tasks
Exercises for Pólya's second stage — Devising a Plan. The goal is to practice finding a strategy before coding: spotting the related/known problem, solving a simpler version first, working backward, and sequencing by risk. Global constraints: (1) For every task, write the plan first — in plain English, numbered steps — and only then (where asked) write code. (2) Each risky plan must name a kill-criterion: the observation that would prove the approach wrong. (3) Keep plans at the right altitude — checkable, not pseudo-code. Pair these with Understanding the Problem (do that first) and Carrying Out the Plan (test the plan after).
Task 1 — Name the known problem¶
For each task below, write one line: "This is really an instance of ___." Don't solve them — just classify.
- "Warn the user if their new password is too similar to the old one."
- "Given build steps with dependencies, find a valid build order."
- "Pick the maximum number of non-overlapping meetings for one room."
- "Find duplicate files across a 2 TB disk."
- "Auto-complete: given a prefix, return all matching product names."
Deliverable: five classifications (e.g., edit distance; topological sort; interval scheduling; hashing; trie/prefix search). The point is recognizing the class — that's where the plan comes from. See pattern recognition.
Task 2 — Solve a simpler version first¶
Problem: "Given an array of stock prices, find the maximum profit from one buy and one later sell."
Write a ladder of plans: 1. Plan for an array of size 2. 2. Plan for size 3. 3. Plan for any size — your first, possibly O(n²), idea. 4. Now generalize the pattern you noticed into an O(n) plan (hint: track the minimum-so-far).
Deliverable: four plans showing the climb from trivial to general. Note which rung gave you the insight for the O(n) version — that's the heuristic working.
Task 3 — Work backward from the goal¶
Goal: "A weekly email to each user summarizing their activity, sent every Monday 9am their local time."
Starting from the goal, chain preconditions backward until you reach data/services you already have. (Email needs content → content needs per-user activity for the week → activity comes from the events table → "their local time" needs each user's timezone → …)
Deliverable: a backward chain of 5–7 preconditions, ending at things that already exist. Mark any precondition you don't currently have — those become the riskiest steps.
Task 4 — Generate three approaches, then choose¶
Problem: "Our search endpoint is slow (p99 = 2.5s); get it under 300ms."
- Write three genuinely different approaches (not three flavors of one).
- For each, fill a row: approach | reduces to (known problem) | key risk | reversibility (one-way / two-way door).
- Choose one and justify in two sentences, citing risk and reversibility.
Deliverable: the comparison table + the choice. This is divergent-then-convergent in practice. If your three approaches are too similar, you haven't diverged enough — try again.
Task 5 — Sequence by risk¶
You're integrating a third-party shipping-rates API into checkout. The raw work items are: build the rate-display UI, model the shipping options in the DB, call the shipping API and parse its response, handle the API being down, add caching for rates.
- Order these riskiest-part-first.
- Justify the first item: why is it the one most likely to invalidate the whole plan?
- State a kill-criterion for it.
Deliverable: an ordered list + justification + kill-criterion (e.g., "If the API doesn't support our shipping regions, the whole feature is blocked — verify with a throwaway script before any UI work; kill-criterion: any required region returns 'unsupported'").
Task 6 — Spike vs. build¶
For each scenario, decide whether the right next move is a spike (throwaway, to learn) or a real implementation, and say what one question the spike answers.
- "We might switch our queue from RabbitMQ to Kafka."
- "Add a 'remember me' checkbox to the login form."
- "Can our current DB handle 10× write volume, or do we need to shard?"
- "Rename the
usrtable tousers."
Deliverable: four decisions, each spike justified by its single question. Note which are two-way doors where over-planning is waste. See spikes & prototypes.
Task 7 — Restate to find the plan¶
Each problem below is stated in a way that hides the plan. Restate it so the path becomes obvious.
- "Make sure no two users can grab the last item in stock at the same time." → restate as a ___ problem.
- "Show users products similar to ones they've viewed." → restate as a ___ problem.
- "Don't let the report job run twice if someone double-clicks." → restate as a ___ problem.
Deliverable: three restatements (e.g., concurrency/locking; similarity/nearest-neighbor; idempotency/deduplication). Notice how the restated form names the technique. Restating is one of Pólya's core heuristics.
Task 8 — Right-altitude plan¶
Take this over-detailed "plan" (coding-in-disguise) and rewrite it at the correct altitude:
1. def import_csv(path): open file with csv.DictReader
2. for row in reader: validate row['email'] with EMAIL_REGEX
3. if invalid: append to errors_list, continue
4. user = User(email=row['email'], name=row['name'])
5. db.session.add(user); if i % 500 == 0: db.session.commit()
...
Deliverable: a 4–6 step plan in plain English stating decisions and sequence (validate-then-insert, batch the commits, collect errors rather than abort) with no syntax. Then write one sentence on a checkable gap the lower-altitude version hid (e.g., "what happens to a duplicate email?").
Task 9 — Plan-or-just-do-it triage¶
For each change, decide: write a plan or just try it? Justify in one phrase using reversibility + blast radius.
- Fix a typo in an error message.
- Change the primary-key type of a 30M-row table from
inttouuid. - Bump a dev dependency's patch version.
- Switch the default sort order of a public API endpoint.
- Adjust the padding on a button.
Deliverable: five decisions. The two that need real planning should be the irreversible / high-blast-radius ones (2 and 4).
Task 10 — Plan as a falsifiable hypothesis¶
Pick any non-trivial task you have on your real backlog. Write its plan as a hypothesis:
HYPOTHESIS: <approach> will achieve <measurable outcome>.
RISKIEST STEP FIRST: <the unknown that could kill it> — kill-criterion: <observation>.
STEPS: <ordered, risk-first>.
DEFINITION OF DONE: <how you'll know it worked>.
Deliverable: the filled template. Then in Carrying Out the Plan, execute it and record where the plan diverged from reality — that gap is the most valuable thing you'll learn.
Task 11 — Decompose a multi-team plan along seams¶
Initiative: "Extract checkout out of the monolith into its own service, with three teams (Checkout, Payments, Platform)."
- Identify the interfaces (seams) between the teams — the contracts each team depends on.
- Describe a walking skeleton: the thinnest end-to-end path through all three teams that proves the seams compose.
- Name the single biggest coordination (non-technical) risk and how the sequence retires it early.
Deliverable: the seams list + walking-skeleton description + the coordination risk. This is the professional-level plan-by-interface move; the seams are the plan.
Task 12 — Post-mortem a plan that died on contact¶
Recall a past project where the plan fell apart mid-execution. Reconstruct:
- What was the original plan (one paragraph)?
- What assumption did reality violate?
- Was that assumption named in the plan, or hidden?
- Could a riskiest-part-first ordering or an explicit kill-criterion have surfaced the problem earlier?
Deliverable: the four answers. The lesson transfers to your next plan via Looking Back: the failure mode you name here is the assumption you'll write down next time.
In this topic
- interview
- tasks