Solving a machine coding round
Open in the interactive app: practice, quiz, mock interview →In one minute
- A machine-coding round gives you a one or two page spec and 90 to 120 minutes to produce working code. The evaluator runs it against sample input, then reads it. Code that does not run scores close to zero, however elegant the classes.
- Spend the first 10 to 15 minutes reading, listing commands and turning the sample input and output into a test. Then build thin vertical slices: one command working end to end before the next starts.
- Scaffold in a fixed order: models, in-memory repositories, services that hold the rules, a parser with a dispatch table, and a thin driver.
- Errors are output, not crashes. A bad line prints an error, the loop keeps going, and a failed command changes no state.
- Most rounds end with "now add X". A dispatch table, a strategy for the one rule most likely to change, and repositories behind an interface make that a 10-minute change.
How it works
What the round is and how it differs from OOD
Many product companies, especially in India, run a machine-coding round: a problem such as a parking lot, a meeting room booker or a Splitwise clone, your own IDE, and a fixed window. At the end you demo it, the evaluator feeds it inputs, then reviews the code for structure and how easily it absorbs a change. The object-oriented design round (covered in the companion lesson on approaching OOD interviews) is a conversation with diagrams where code is optional. Here working code is required, and the design is judged by reading it. The score depends on three things, in order: does it run and print the right output, can a reviewer find each rule in one place, and does the next requirement fit without surgery.
A time plan
For a 90-minute round:
| Minutes | Activity | Output |
|---|---|---|
| 0 to 10 | Read twice, list commands, ask questions | Commands with exact output formats |
| 10 to 15 | Sample input as a failing test; sketch entities | One golden test, a few class names |
| 15 to 30 | Models, repositories, parser, first command end to end | Something that runs |
| 30 to 65 | One vertical slice per remaining command | All happy paths pass |
| 65 to 80 | Validation, error lines, edge-case tests | Bad input never crashes |
| 80 to 90 | Run the full sample, rename, delete dead code | Demo ready |
For 120 minutes, keep the shape and spend the extra time on edge cases and the "optional" requirement. If two commands are missing at minute 60, stop polishing and finish them.
Ask only questions that change structure or output: case-sensitive keywords, exact error text, half-open intervals, tie-breaks, id reuse. Write each answer at the top of the test file; it becomes your spec.
Scaffolding order
- Models. Plain data:
Room(name, capacity),Booking(id, user, room, start, end). - Repositories. In-memory stores with
add,get,removeand the one or two queries the rules need (for_room). They own id generation and contain no business rules. - Services. Every rule lives here: "smallest room that fits", "only the owner can cancel". They take repositories in the constructor, raise domain errors, and never print or parse.
- Parser and dispatcher. Tokenise, look the keyword up in a table of
name -> (arity, handler), check the count, convert numbers, call the service, format the result. This is the Command pattern in its lightest form (see Command). - Driver. Read lines, call
execute, print. No logic, so no test needed.
In-memory repositories
A map keyed by id gives O(1) lookups, which is enough for nearly every round. Hiding the map behind methods lets you answer "how would you persist this?" with "implement this interface against a table" rather than "rewrite the service". Advance the id counter only when a write succeeds, so a rejected command does not shift every later output.
Command parsing that does not crash
Treat every line as hostile: blank, extra spaces, lowercase keyword, wrong argument count, a word where a number belongs. Validate in a fixed order (keyword, arity, number format, domain rules) so the error for a bad line is predictable. Domain errors share one type; the dispatcher catches that type, prints ERROR <message> and moves on.
Tests
A golden test feeds the spec's sample input and compares the full output; it catches format slips that evaluators' scripts are unforgiving about. Focused tests cover each rule and its edges: ties, boundaries, owner checks, and "a failed command changes nothing". Inject anything nondeterministic so tests repeat, as Design Snake and Ladder Game does with its dice and Design Movie Booking System with hold expiry.
Extensibility the evaluator will probe
With a dispatch table a new command is one entry plus a service method. The rule most likely to vary (which spot, which room, how to split) belongs behind a strategy: Design Parking Lot does this for spot choice and Design Splitwise for split types. Do not pre-build interfaces for everything; make the two likely changes cheap (see YAGNI Principle).
The same shape elsewhere
An interpreter over in-memory state is the finding things fast shape (keyword to handler, id to entity) wrapped around a state machine. Redis is exactly this: a command table mapping each name to a handler and an arity, and a loop that parses, checks and runs each request against in-memory data.
Down the stack
Layer 1The contract
Every input line produces exactly one output line, or none for a blank or comment line. Output is a pure function of the lines seen so far. A rejected command emits ERROR ... and leaves every repository and id counter unchanged. No input line can terminate the process. The practice tests check each statement.
Layer 2The mechanism
Whitespace tokenising is O(line length). The dispatcher is a hash map from the uppercased keyword to an arity and a handler. Redis stores the same idea: a positive arity means exactly that many arguments including the name, a negative one means at least that many, and the server checks it before calling the handler. Numbers pass a strict digits-only check, so -5, 1e3 and 12abc fail the same way. The service reads repositories and writes only after every check passes, which makes a failed command atomic without rollback code.
Layer 3The machine
Go's bufio.Scanner stops with "token too long" on lines over 64 KiB unless you call Buffer, a surprise when a sample file holds one huge line. Writing is the bigger trap: Go's os.Stdout is unbuffered, so fmt.Println per line is one write syscall, around a microsecond each; 100,000 lines spend a tenth of a second in syscalls alone. Wrap it in a bufio.Writer and flush at exit. Splitting allocates: Python creates a new string object (about 50 bytes of header) per token, while Go's strings.Fields returns substrings sharing the line's bytes.
Why it's built this way
- Evaluators judge by running sample input, so exact output and "never crash" matter more than any pattern.
- Running something early is the only defence against the clock, so build vertical slices, not one layer at a time.
- Each rule must be findable and testable alone, so rules live in services, away from parsing and printing.
- The last 20 minutes usually bring a change request, so commands, the main allocation rule and storage sit behind a table, a strategy and a repository.
Diagram
flowchart LR
IN["Input line"] --> TOK["Tokenise"]
TOK --> DISP{"Keyword in table?"}
DISP -- no --> ERR["ERROR line"]
DISP -- yes --> AR{"Arity and numbers ok?"}
AR -- no --> ERR
AR -- yes --> SVC["Service: rules"]
SVC -- "domain error" --> ERR
SVC --> REPO["In-memory repositories"]
SVC --> FMT["Format result"]
FMT --> OUT["Output line"]
ERR --> OUTWorked example
The spec: a meeting room booker with ADD_ROOM, BOOK, CANCEL, FREE and SCHEDULE; book the smallest room that fits, ties by name; 90 minutes. Minutes 0 to 10: the candidate asks whether intervals are half-open (yes), whether ids advance on failed bookings (no) and whether lowercase keywords are allowed (yes). Minutes 10 to 15: the sample goes into a golden test:
ADD_ROOM big 10 -> ADDED big
ADD_ROOM small 4 -> ADDED small
BOOK alice 540 600 3 -> BOOKED B1 small
BOOK bob 540 600 3 -> BOOKED B2 big
BOOK cara 540 600 3 -> ERROR no room availableMinutes 15 to 30: models, two repositories and the dispatcher with only ADD_ROOM; it runs. Minutes 30 to 60: the other four commands, about 7 minutes each. Minutes 60 to 80: error paths, half-open boundaries (540-600 and 600-660 coexist) and a test that a rejected booking does not consume B3. The change request, "rooms can go under maintenance", is one dispatch entry, a blocked flag and one condition in the free check.
Trade-offs
| Choice | Strengths | Weaknesses | Choose when |
|---|---|---|---|
| Single file | Fast to start | Hard to read past 300 lines | Two or three commands |
| Layered (models, repos, services, commands) | Each rule has one home | Ten minutes of scaffolding first | Almost every round |
| Exceptions for domain errors | One catch in the dispatcher | A broad catch hides bugs | Python, TypeScript, Java |
| Secondary index | Fast queries | Kept in sync on every write | Spec mentions large inputs |
Pitfalls in production
- Printing inside services. Rules become untestable without capturing stdout. Fix: services return values, the dispatcher formats.
- One giant
ifchain on the keyword. Each new command edits a 200-line function. Fix: a dispatch table. - Ids that advance on failure. One rejected line shifts every later id and the golden output diverges. Fix: allocate the id after validation.
- A broad catch. A
KeyErrorin your own code becomes a plausibleERRORline. Fix: catch only the domain error type. - Unbuffered output in Go. Large inputs time out in the harness. Fix: a
bufio.Writerflushed at exit.
Leadership lens
- Machine coding is a fair proxy for daily work: a vague ticket, a deadline, and code a teammate extends next week. Calibrate interviewers to grade "runs and is extendable" over "used many patterns".
- Put concrete signals in the rubric: golden test present, rules isolated from I/O, failed commands leave no trace, change request absorbed in a few files.
- When an assistant writes the scaffolding, check its boundaries: generated code tends to print from services and catch every exception.
Check yourself
At minute 60 you have three of five commands working and want to refactor a long handler. What should you do?
Show answer
Finish the two missing commands first. A missing command fails the evaluator's run outright, while a long handler costs a little readability.
Why should the repository own id generation, and when should the counter advance?
Show answer
Ids are a storage concern and must be unique across all writers. The counter advances only when a write happens, so rejected commands do not shift later ids.
Your dispatcher catches all exceptions and prints
ERRORplus the message. What is the risk?Show answer
A real bug prints a plausible error line and tests may still pass. Catch only the domain error type so bugs crash in tests.
How do you make a failed
BOOKleave no trace without rollback code?Show answer
Run every validation and the room search before any write, so the only write is the final insert.
Watch
- Machine Coding Round Interview: Flipkart, Uber, Udaan, Dunzo (CodeBuddy Official): what companies expect in the round and how candidates are evaluated.
- Machine Coding Interview Round: Design and Code a Stock Broker App (Keerti Purswani): a live, timed walkthrough from requirements to running code.
- Machine coding round: A Step-by-Step Guide (Engineerhoon): a step-by-step approach to pacing and structuring a solution.
Free resources
- Repository (Martin Fowler, Patterns of Enterprise Application Architecture): the pattern behind in-memory stores that can later be swapped for a database.
- Command pattern (Refactoring.Guru): commands as objects, the idea behind a dispatch table of handlers.
- COMMAND (Redis docs): how a real server describes each command's name, arity and flags in its command table.
- cmd: support for line-oriented command interpreters (Python docs): the standard library's own interpreter skeleton, with dispatch by method name.
- bufio (Go docs):
Scannerlimits andWriterbuffering, the two I/O details that bite in timed rounds. - The Practical Test Pyramid (Martin Fowler): how focused unit tests and a few broad end-to-end tests fit together.