DocumentationProblem kinds and tracks

Guides

Problem kinds and tracks

Every problem runs through the same commands, but not every problem has the same shape. This page explains each kind, and what changes for it.

On this page
  1. Tracks
  2. Function and design problems
  3. Progressive problems
  4. Concurrent problems
  5. Debugging problems
  6. Project problems
  7. System design and code review

Tracks

The catalog is organised in tracks. 5 are graded by running your code; 2 are prompts you answer in notes and grade yourself with a rubric. These are the counts in cstudy 0.8.0:

Tracks and their problem counts
TrackItemsGraded byWhat you practise
Data structures and algorithms dsa196Tests, in every languageFunctions and data-structure designs across 23 patterns
Practical practical28Tests, level by levelOne class whose API grows over levels, a project folder, or a business task with money and dates
Low-level design lld8Tests, then a design rubricObject-oriented design
Concurrency concurrency6Stress tests against invariantsThread-safe classes, with a concurrency model per language
Debugging debugging16TestsBuggy code to fix, including bugs that exist only in Go or Rust
System design system-design10Yourself, with a rubricA prompt, a notes template and a reference design
Code review code-review6Yourself, with a rubricA change to review, and the issues a strong reviewer finds

Correctness is always behavioural: cstudy sends the inputs of a case to your code, and compares what it returns with the expected value. Your code is never compared with the reference solution’s text, so any correct approach passes. Every problem is listed in the catalog.

Function and design problems

Most problems ask for one function. The signature is declared once and mapped to each language, so two_sum(nums: list[int], target: int) in Python is fun twoSum(nums: IntArray, target: Int) in Kotlin. Where several answers are valid, the comparator accepts any of them: in any order for an unordered result, or by checking the answer itself.

A design problem asks for a class, such as an LRU cache. Each case is a sequence of operations: construct the class, then call its methods in order, and every result is compared.

The low-level design track uses design problems too. The tests check the public behaviour; after you finish, cstudy solution shows a rubric of design criteria for self-review, then a reference design, before the code.

Progressive problems

A progressive problem is one class whose API grows over levels, such as an in-memory store that adds scans, then expiry, then history. Time is always an explicit timestamp argument, never a clock.

  • A new attempt opens level 1. The statement shows the open levels only; later titles stay hidden.
  • The stub already lists every method, each marked with its level, so later method names are visible; their rules are not.
  • cstudy test runs the cases of the open levels. A run that passes all of them opens the next level and rewrites the statement. Use --level N to run fewer levels.
  • Only a pass of every level is a full pass, which cstudy done --rating needs.
terminal
$ cstudy test
level-store · python · level 1 of 3 · 4 cases (1 visible, 3 hidden, 0 generated)

PASS     ex1   0.02ms
PASS     3 hidden cases

4/4 passed · total 0.3s
level 1 passed · unlocked level 2 of 3: Remove and size
statement  .statements/level-store.md (updated)

Concurrent problems

A concurrent problem asks for a thread-safe class, such as a bounded blocking queue. Besides ordinary cases, it has stress cases: many threads or tasks call your class at once, and cstudy checks invariants over everything they recorded, for example that every item put was taken exactly once. Each language uses its own model: threads in Java and Kotlin, threads or asyncio in Python, and async on Node’s event loop in TypeScript. Java and Kotlin can run a stress case on both platform and virtual threads, as 2 variants.

terminal
$ cstudy test bounded-blocking-queue --lang java
bounded-blocking-queue · java · 6 sequential (2 visible, 4 hidden) · 2 stress × 2 variants × 3 runs
build  1.6s (gradle, warm)

PASS     ex1   0.05ms
PASS     ex2   0.04ms
PASS     4 hidden cases
PASS     s1    platform · 3/3 runs · median 38ms
FAIL     s1    virtual · 1/3 runs passed
         run 0 · seed 1000  equal_multisets put.arg0 vs take: 2 missing (1000017, 3000431), 0 extra
         run 2 · seed 1002  distinct take: 2000005 (2 times)
STALLED  s2    platform · 0/3 runs passed · deadline 5000ms
         run 0 · seed 2000  producer[0] in put (op 704 of 1000) · consumer[0..2] in take
PASS     s2    virtual · 3/3 runs · median 61ms

8/10 passed · 1 failed · 1 stalled · total 4.9s
  • STALLED means a run was still unfinished at its deadline: usually a deadlock or a missed wake-up. The line says where each thread was waiting.
  • A failing run prints its seed. Rerun it with --case s1 --seed 1007 --stress 1; in the async model this reproduces the run exactly. --stress N runs each stress case N times.
  • A pass is evidence, not proof: the summary says stress runs found no race (not a proof of thread safety).
  • cstudy solution --broken shows a deliberately broken reference with an explanation of its bug, as a spot-the-bug exercise.

Debugging problems

A debugging problem starts you with buggy code instead of an empty stub. Fix it until the tests pass. Some bugs exist only in some languages, such as integer overflow or a mutable default argument, so a debugging problem may be available in fewer languages, and a few exist only in Go or only in Rust.

Project problems

A project problem is a folder of seeded files in one language: an entry class, model types, a test fixture and build files. You edit those files or add your own, and the problem opens in levels that build on the same code. cstudy 0.8.0 has 6, one in each of Python, TypeScript, Java, Kotlin, Go, Rust, with these levels: Accounts and transfers; Top spenders; Scheduled transfers; Merges and balance history.

Starting

cstudy start copies the starter folder to projects/<slug>/, writes level 1’s test file, and opens the folder and the statement. It never overwrites a file you already have.

terminal
$ cstudy start bank-project-python
bank-project-python · hard · practical · python · project
project    projects/bank-project-python (6 files)
entry      bank/bank.py: Bank
tests      tests/test_level_1.py (2 tests)
statement  .statements/bank-project-python.md
level      1 of 4: Accounts and transfers
next       cstudy test --watch, then cstudy submit

Test, then submit

cstudy test compared with cstudy submit on a project problem
Aspectcstudy testcstudy submit
RunsThe project’s own tests, with the language’s native frameworkEvery case of the open levels, visible and hidden
PurposeFeedback while you workGrading
Opens the next levelNeverWhen every case of every open level passes
Debugging--debug stops in your code and your testsNever debugged
terminal
$ cstudy submit
bank-project-python · python · submit levels 1-2 of 4 · timer 33:05 / 90:00

level 1  PASS     5/5 (2 visible, 3 hidden)
level 2  FAIL     4/5 (2 visible, 3 hidden)
FAIL     h3    hidden · level 2
         input     ops ["Bank", "create_account", ...]  args [[], [1, "zoe"], ...]
         expected  ["abe(60)", "zoe(60)", "mia(0)"]
         actual    ["zoe(60)", "abe(60)", "mia(0)"]

9/10 passed · level 3 opens when levels 1-2 pass

A submission that passes every open level opens the next one, and tells you what the level adds:

text
10/10 passed · level 3 unlocked: Scheduled transfers
add        schedule_transfer(timestamp: int, source_id: str, target_id: str, amount: int, delay: int) -> str, cancel_transfer(timestamp: int, account_id: str, transfer_id: str) -> bool
tests      tests/test_level_3.py (2 tests)
statement  .statements/bank-project-python.md (updated)

Every submission grades all open levels again, because later rules can change earlier results. Grading uses the cases in the problem, never your test files, so editing a test cannot change a grade.

Generated level tests

When a level opens, cstudy writes one native test file with that level’s visible cases. The files are yours to edit and extend; cstudy never rewrites them.

Generated test files per language
LanguageFileFramework
Pythontests/test_level_1.pypytest
TypeScriptlevel-1.test.tsnode:test
JavaLevel1Test.javaJUnit 5
KotlinLevel1Test.ktkotlin.test on JUnit 5
Golevel_1_test.gogo test
Rusttests/level_1.rscargo’s test harness

Where you stand

cstudy status shows the open level, your latest test run and submission, and which files you changed, without running anything.

terminal
$ cstudy status
bank-project-python · python · project · attempt 41 · new
level      2 of 4: Top spenders (opened 18:02)
timer      33:05 / 90:00
tested     3/4 passed, 1 min ago
submitted  level 1 5/5 · level 2 4/5, 2 min ago
files      2 changed, 1 added, 0 removed against the starter
next       cstudy submit once level 2 passes

Deleted or broke a starter file or a generated test? cstudy start <slug> --restore PATH writes that one file back as cstudy provides it, and does nothing else.

terminal
$ cstudy start bank-project-python --restore tests/test_level_2.py
bank-project-python · hard · practical · python · project
restored   tests/test_level_2.py (level 2 tests)

Finishing

cstudy done grades a project attempt from your latest submission of every open level. Finishing every level allows any grade; finishing all but the last caps it at hard; fewer grades it again. Hints open with the levels: while the next hint belongs to a locked level, cstudy hint says so.

System design and code review

These items have no tests. cstudy start copies a notes template to notes/<track>/<slug>.md and renders the prompt; a code review prompt includes the change to review.

terminal
$ cstudy start url-shortener
url-shortener · medium · system-design · 45 min
notes      notes/system-design/url-shortener.md
prompt     .statements/url-shortener.md
next       answer in the notes, then cstudy solution url-shortener

Answer in the notes, then run cstudy solution: it shows the rubric, what a strong answer covers, and the reference. Comparing them is the review, so revealing never lowers the grade, and cstudy done --rating schedules the item like any problem.

Study guides

System design items can link to sections of your own study notes. Set root under [study_guides] in your configuration, and statements gain a list of links to the guides that exist under it.

Written for cstudy 0.8.0. The specs in the cstudy repository are the source of truth for every detail.