The practice notebook 02 · Coding

CoderPad interview practice. Explain, code, test.

Get comfortable with the editor, then rehearse the work that matters. Try three original timed exercises in Python, explain your decisions aloud, and compare your solution only after a first attempt.

Original exercises
3
Per exercise
15–25 min
Worked solutions
Python 3

Before the timer

Learn the editor, then close the reference

CoderPad’s official candidate guide describes a browser-based interview environment where you write and run code. Its sandbox guide recommends trying execution, editor settings, and language information before the interview.

  1. Open the official CoderPad sandbox or a local Python 3 editor. Choose Python and run a tiny assertion such as assert 2 + 2 == 4. Add print("passed") so successful execution is visible.
  2. Check the pad’s language information for the actual runtime and available libraries. Adjust indentation and key bindings so basic editing feels familiar.
  3. Keep an independent copy of your practice code. The official sandbox documentation says tabs and contents are removed after an hour of inactivity; do not treat it as permanent storage.
  4. Set a separate timer. Read the problem and tests, then close this guide while you work. The exercises below need only Python’s standard library.

Original exercises. Independent guide.

ClawPad is not affiliated with CoderPad. These are practice problems written for this guide, not official CoderPad questions or leaked employer assessments. For an actual interview, follow the organizer’s rules about AI, reference material, and collaboration.

Official documentation checked October 11, 2026. We verified the published setup guidance, not a live employer pad or its configured features.

A repeatable routine

Show your thinking before you optimize

Restate the input, output, and one ambiguous edge case. Walk through a small example by hand. Describe a correct approach before typing, then implement the smallest complete version. Run the tests and explain why the algorithm works.

Think aloud at decision points: “I need the original order, so I will count first and scan again.” Continuous narration is unnecessary. If you get stuck, state the uncertainty and construct a smaller example.

These time limits are practice targets, not CoderPad requirements. Try one exercise per session. Across later sessions, progress from counting to intervals to graphs.

The practice set

Three exercises, with the solutions kept closed

Copy the assertions beneath your function. Python assertions produce no output when they pass, so add print("All checks passed") after them. The examples check important cases; explain why your solution handles other valid inputs too.

Exercise 1 · 15 minutes

Find the one-off support ticket

Counting · preserving order

A support export contains ticket IDs in arrival order. A repeated ID means the ticket was retried. Return the first ID that occurs exactly once in the entire export, or None if there is no such ID. Do not change the input list.

Contract: Implement first_unique_ticket(tickets). Input is a list of 0 to 100,000 case-sensitive strings, each 1 to 64 characters long. The return value is a string or None. Inputs already satisfy this contract; validation is outside this exercise.

first_unique_ticket(["a", "b", "a", "c"]) == "b"

Your time budget: Spend 3 minutes clarifying “first” and proposing an approach, 8 minutes implementing, and 4 minutes testing and explaining complexity.

Tests to run

assert first_unique_ticket([]) is None
assert first_unique_ticket(["a"]) == "a"
assert first_unique_ticket(["a", "a"]) is None
assert first_unique_ticket(["a", "b", "a", "c"]) == "b"
assert first_unique_ticket(["a", "b", "b", "a"]) is None
assert first_unique_ticket(["A", "a"]) == "A"
assert first_unique_ticket(["é", "x", "é"]) == "x"
tickets = ["a", "b", "a"]
assert first_unique_ticket(tickets) == "b"
assert tickets == ["a", "b", "a"]
Reveal worked solution for exercise 1
def first_unique_ticket(tickets):
    counts = {}
    for ticket in tickets:
        counts[ticket] = counts.get(ticket, 0) + 1

    for ticket in tickets:
        if counts[ticket] == 1:
            return ticket
    return None

Why this is correct

The first pass records the total count of every ID. The second pass visits IDs in their original order, so the first count of one is exactly the requested result. A single occurrence seen so far is not enough; a later retry could disqualify it.

Time and space

Expected O(n) time and O(u) extra space, where n is the number of tickets and u is the number of distinct IDs. String lengths are bounded by the contract. This uses the usual expected constant-time dictionary operations.

One follow-up to try

What changes if tickets arrive in a stream that never ends? You cannot declare an ID globally unique before the stream ends. Explain what a provisional answer would mean before changing the algorithm.

Exercise 2 · 20 minutes

Combine maintenance windows

Sorting · interval boundaries

A service team schedules maintenance using minute offsets from the start of a day. Combine overlapping or touching windows and return the resulting windows sorted by start time. Keep the input unchanged.

Contract: Implement merge_windows(windows). Input is a list of 0 to 100,000 pairs (start, end) of integers with 0 ≤ start < end ≤ 1440. Each pair is a half-open interval [start, end). By product choice, touching intervals such as (10, 20) and (20, 30) are combined. Return a list of tuples. Inputs are valid; zero-length intervals are excluded.

merge_windows([(40, 60), (10, 20), (20, 45)]) == [(10, 60)]

Your time budget: Spend 4 minutes defining overlap and touching, 11 minutes implementing, and 5 minutes checking boundaries and the reason sorting helps.

Tests to run

assert merge_windows([]) == []
assert merge_windows([(10, 20)]) == [(10, 20)]
assert merge_windows([(20, 30), (10, 20)]) == [(10, 30)]
assert merge_windows([(10, 40), (20, 30)]) == [(10, 40)]
assert merge_windows([(10, 20), (10, 20)]) == [(10, 20)]
assert merge_windows([(0, 1), (1439, 1440)]) == [(0, 1), (1439, 1440)]
assert merge_windows([(40, 60), (10, 20), (20, 45)]) == [(10, 60)]
windows = [(30, 40), (10, 20)]
assert merge_windows(windows) == [(10, 20), (30, 40)]
assert windows == [(30, 40), (10, 20)]
Reveal worked solution for exercise 2
def merge_windows(windows):
    merged = []
    for start, end in sorted(windows):
        if not merged or start > merged[-1][1]:
            merged.append((start, end))
        else:
            previous_start, previous_end = merged[-1]
            merged[-1] = (previous_start, max(previous_end, end))
    return merged

Why this is correct

After sorting, a new window cannot overlap an earlier finished group without also reaching the last group. The result remains sorted and separated after each step. Extend only the last group when start is at or before its end. Taking the maximum end preserves a larger window when another is nested inside it.

Time and space

O(n log n) time for sorting plus an O(n) scan, with O(n) space for the sorted copy and output. Here n is the number of input windows. The bounded minute range also allows other approaches; this one generalizes to larger timestamp ranges.

One follow-up to try

If touching windows must remain separate, which comparison changes? Use start >= merged[-1][1] to start a new group, then update the touching-boundary test. Explain why half-open intervals make that distinction meaningful.

Exercise 3 · 25 minutes

Find the shortest team handoff

Graphs · breadth-first search

A directory lists which teams can hand a request directly to other teams. Find a route from a starting team to a destination using the fewest handoffs. Each handoff has equal cost. Return the route, including both endpoints, or None when no route exists.

Contract: Implement shortest_handoff(graph, start, goal). The directed graph maps case-sensitive team names to lists of neighboring names. A missing key has no outgoing edges. Cycles and duplicate edges are allowed. If start equals goal, return [start], even if the name is absent from the graph. For equal-length routes, return the one discovered first using each adjacency list’s order. Inputs are valid; do not mutate them.

shortest_handoff({"help": ["billing", "ops"], "billing": ["risk"], "ops": ["risk"]}, "help", "risk") == ["help", "billing", "risk"]

Your time budget: Spend 5 minutes clarifying direction and equal costs, 14 minutes implementing, and 6 minutes testing cycles, unreachable teams, and ties.

Tests to run

graph = {
    "help": ["billing", "ops"],
    "billing": ["help", "risk"],
    "ops": ["risk"],
}
assert shortest_handoff(graph, "help", "risk") == ["help", "billing", "risk"]
assert shortest_handoff(graph, "risk", "help") is None
assert shortest_handoff({}, "solo", "solo") == ["solo"]
assert shortest_handoff({}, "a", "b") is None
assert shortest_handoff({"a": ["a", "b", "b"]}, "a", "b") == ["a", "b"]
assert shortest_handoff({"a": ["b"], "b": ["a"]}, "a", "c") is None
assert shortest_handoff({"a": ["b", "c"], "b": ["c"]}, "a", "c") == ["a", "c"]
assert graph == {"help": ["billing", "ops"], "billing": ["help", "risk"], "ops": ["risk"]}
Reveal worked solution for exercise 3
from collections import deque


def shortest_handoff(graph, start, goal):
    queue = deque([start])
    previous = {start: None}

    while queue:
        team = queue.popleft()
        if team == goal:
            path = []
            while team is not None:
                path.append(team)
                team = previous[team]
            return path[::-1]

        for neighbor in graph.get(team, []):
            if neighbor not in previous:
                previous[neighbor] = team
                queue.append(neighbor)
    return None

Why this is correct

Breadth-first search visits teams in nondecreasing distance from the start. Marking a team when it enters the queue prevents cycles and preserves its first, shortest predecessor. Processing neighbors in list order gives the requested tie behavior. Following predecessors from the goal and reversing the result reconstructs the route.

Time and space

Expected O(V + E) time and O(V) extra space for the reachable portion of the graph. V is the number of reachable teams and E counts their outgoing adjacency entries, including duplicates. Team-name dictionary operations use expected constant time under a bounded-name-length assumption. Reconstructing a path takes at most O(V) time and space.

One follow-up to try

What if a handoff has a different delay on each edge? Fewest edges may no longer mean lowest total delay. Explain the changed objective and consider Dijkstra’s algorithm when every delay is nonnegative.

After the timer

Save a diagnosis, not just a passing function

For each point below, mark independent, needed a hint, or not yet. Keep the evidence beside the mark. This is a practice checklist, not a prediction of a hiring decision.

  • Contract. I clarified ordering, mutation, boundaries, and the empty-input result before coding.
  • Correctness. I can explain an invariant or argument that covers all valid inputs, not only the example.
  • Testing. I ran the given cases and added one that could break my first idea.
  • Complexity. I defined the input-size variables and included sorting, copying, and stored state.
  • Communication. I explained a decision and responded to the follow-up without reading the solution.

If the solution required a hint, close it and implement it again from a blank editor in a later session. Change one constraint and explain what breaks. Track time only alongside correctness and how much help you needed.

Round out your preparation with behavioral interview practice and the STAR story builder. For architecture questions, try the system-design hub. The AI mock practice guide shows how to use feedback after an unaided attempt.

Official references

These sources support the editor setup advice. The exercise wording, solutions, time budgets, and review checklist are original editorial material.

Common questions

Are these official CoderPad interview questions?

No. These are original ClawPad practice exercises using common programming patterns. ClawPad is not affiliated with CoderPad. The exercises do not represent an employer’s question bank or predict what you will be asked.

Can I practice without an interview invitation?

CoderPad publishes a candidate sandbox for exploring its editor. Follow the official sandbox link in this guide and check the current access instructions there. You can also run all three exercises in a local Python 3 interpreter without CoderPad.

Do I need external Python packages?

No. The worked solutions use built-in Python features and collections.deque from the standard library. Check the language information in your actual pad because available versions and packages may change.

Can I use AI during a CoderPad interview?

Ask the organizer what assistance is permitted and follow the assessment rules. These exercises are for preparation. During practice, make an unaided attempt before opening the solution or requesting feedback, then repeat without help.