DocumentationWriting your own problems
Guides
Writing your own problems
Add the problems you want to drill: cstudy new scaffolds them, cstudy verify checks them, and they join the catalog for every command.
On this page
Where your problems live
Problems you write go in your workspace’s problems/ directory, numbered from 5001, so new catalog problems never take your ids. cstudy overlays them on the catalog: cstudy list, next, start, test and verify treat them like any other problem.
If one of your problems uses the slug of a catalog problem, yours wins and hides the catalog one entirely, so your practice files and progress always match the problem you wrote.
Scaffold one with cstudy new
cstudy new max-gap --from-template array --pattern arrays-hashing --difficulty mediumcstudy new creates the problem’s directory with status: draft, every required file with TODO placeholders, and prints the next steps with the check for each. The title defaults to one made from the slug (max-gap becomes Max Gap), the difficulty to medium.
| Template | Shape | Default track |
|---|---|---|
array | A function taking an int array and an int, returning an int (the default) | dsa |
tree | A function taking and returning a binary tree | dsa |
design | A class with a constructor and 2 methods, tested with operation sequences | dsa |
progressive | A class with 4 levels, one method per level | practical |
concurrent | A thread-safe class with a blocking method, one stress case and one broken reference | concurrency |
project-python | A project folder with an entry class and 2 levels; also project-typescript, project-go, project-java, project-kotlin and project-rust | practical |
| Flag | Effect |
|---|---|
--from-template NAME | One of the templates above |
--track T | dsa, practical, lld, concurrency or debugging; lld also writes a rubric.md |
--pattern P | The primary pattern; a dsa problem needs one, from this flag or the template |
--difficulty D | easy, medium or hard |
--title TEXT | The title |
The files of a problem
| File | Holds |
|---|---|
problem.md | The statement: Statement, Input, Output, Examples, Constraints and Hints sections, in your own words |
meta.yaml | Title, difficulty, track, patterns, the signature in a small type language, the comparator, approaches and performance settings |
tests.json | The cases, as language-neutral JSON: visible examples, hidden cases, and generated ones |
generator.py | Generates random inputs, for oracle checks and benchmarks |
solutions/ | explanation.md, one section per approach, and a reference file per approach and language |
A languages line in meta.yaml lists the languages the problem supports; cstudy new writes it explicitly.
The workflow
Write a problem in this order, running the check after each step:
| Step | Action | Check |
|---|---|---|
| 1 | cstudy new with a template | The directory exists, as a draft |
| 2 | Write problem.md in your own words | cstudy verify <slug> --static |
| 3 | Set the signature and comparator in meta.yaml | --static |
| 4 | Add visible examples and hidden edge cases to tests.json | --static |
| 5 | Write a brute-force approach in Python, marked as the oracle | cstudy verify <slug> |
| 6 | Write generator.py | cstudy verify <slug> --oracle |
| 7 | Write the optimal approach in each language | --oracle |
| 8 | Write solutions/explanation.md | --static |
| 9 | Add the performance block and a generated case at the largest size | --ladder |
| 10 | Set status: ready | cstudy verify <slug> --oracle --ladder --require-ready |
Concurrent problems replace the oracle and ladder steps with stress cases and broken references that the stress cases must catch. Project problems shape a starter folder and a reference overlay instead. A draft is fully practicable, but cstudy next skips it until it is ready.
Checking with cstudy verify
cstudy verify checks problems statically (schema, sections, types of the test values against the signature) and by running every reference solution against the cases in every language.
$ cstudy verify
0001-two-sum static ok · py 2/2 ok · ts 1/1 ok · java 1/1 ok · kt 1/1 ok · oracle 200/200
0014-koko-eat... static ok · py 2/2 ok · ts - · java 1/1 ok · kt - draft (coverage 2/4)
0031-word-break FAIL static: solutions/explanation.md missing "### Correctness" in approach memo-dp
0190-bounded-... static ok · py 2/2 ok · ts 1/1 ok · java 2/2 ok · kt 2/2 ok · stress 10/10 · slowest 8% · broken caught 11/11
coverage python 31/31 · typescript 29/31 · java 31/31 · kotlin 28/31
result 1 failed · 30 passed| Flag | Effect |
|---|---|
--static | Schema and static checks only; nothing runs |
--oracle [--oracle-cases N] | Cross-check every approach against the oracle on N random small inputs (default 200) |
--ladder | Benchmark the references and check their growth against the declared complexity |
--require-ready | Fail any problem whose status is not ready |
--lang L | Check one language |
--track T | Check one track |
--jobs N | Language runners in parallel |
--stress N | Concurrent problems: runs per stress case and variant (default 10) |
--changed | Only problems changed relative to main in git |
Exit code 0 means every check passed, 1 a failed check, and 5 static failures only.
Ready means
For an algorithms problem: at least 2 approaches, a Python oracle, a generator, at least 2 visible and 8 hidden cases, a generated case at the largest size, and an optimal reference in every language the problem lists.
The authoring spec has the full workflow and ready criteria, and the problem format spec defines every file.
Written for cstudy 0.8.0. The specs in the cstudy repository are the source of truth for every detail.