DocumentationPractising

Guides

Practising

The daily loop in detail: how to start and test a problem, when to use hints, how a grade is computed, and how cstudy decides what you practise next.

On this page
  1. The loop
  2. Choosing a language
  3. Starting and resuming
  4. Testing
  5. Hints and solutions
  6. Finishing an attempt
  7. Reviews and spaced repetition
  8. What cstudy next picks
  9. Checking performance
  10. Timers and mock interviews
  11. Tracking progress

The loop

Every problem goes through the same commands, whatever the language:

the core loop
cstudy next  ->  cstudy start <slug> --lang kotlin  ->  edit in your editor  ->  cstudy test --watch
         ->  cstudy bench (optional)  ->  cstudy done --rating ok  ->  cstudy solution (optional)

Commands that take a problem accept its slug (two-sum), its id, or the path of one of your solution files. Without one, they act on the active attempt: your most recent attempt still in progress.

Choosing a language

Pass --lang python, typescript, java, kotlin, go or rust to cstudy start, or set default_lang in your configuration. Reviews are scheduled per problem, so you can solve a problem in one language and review it in another.

A file path names both the problem and the language, which is how editors run cstudy on the open file: cstudy test python/practice/two_sum.py is cstudy test two-sum --lang python.

Where cstudy writes each language's stub
LanguageYour solution file
Pythonpython/practice/two_sum.py
TypeScripttypescript/practice/two-sum.ts
Javajvm/java/src/main/java/practice/two_sum/Solution.java
Kotlinjvm/kotlin/src/main/kotlin/practice/two_sum/Solution.kt
Gogo/practice/two_sum/two_sum.go
Rustrust/practice/two_sum.rs

Starting and resuming

cstudy start <slug> writes the stub, renders the statement to .statements/<slug>.md, begins an attempt and opens both files in $VISUAL or $EDITOR. Starting a problem you already have in progress in the same language resumes that attempt and keeps your file.

cstudy start flags
FlagEffect
--lang LThe language; default: default_lang
--freshMove your existing file to .archive/ and write a new stub; reviews always start fresh
--timer 25mA time box, such as 25m or 1h; finishing over it caps the grade at hard
--no-openDo not launch the editor

Set open_on_start = false in your configuration if you never want cstudy to launch the editor.

Testing

cstudy test runs your code against the problem’s cases. With --watch it runs again each time you save. Visible cases are always listed; passing hidden cases collapse into a count unless you pass --all; a failing hidden case shows its input, the expected answer and yours.

terminal
$ cstudy test --time-limit
two-sum · kotlin · 14 cases (2 visible, 11 hidden, 1 generated) · time limit 5x · timer 12:31 / 25:00
build  1.8s (gradle, warm)

PASS     ex1   0.04ms
PASS     ex2   0.03ms
FAIL     h3    hidden
         input     nums=[-3, 8, 0, 3]  target=0
         expected  [0, 3]  (unordered)
         actual    [3, 3]
TLE      g1    hidden · 412ms > limit 95ms (5x hash-map, calibrated)
PASS     10 hidden cases

12/14 passed · 1 failed · 1 tle · total 2.6s
Case statuses
StatusMeaning
PASSThe comparator accepted your output
FAILWrong answer
ERRORYour code raised an exception or crashed
TIMEOUTThe hang guard (10 seconds by default) stopped a run that did not finish
TLERight answer, but over the time limit (only with time limits on)
INVALIDYour output cannot be read as the declared type
STALLEDA concurrent stress run was still unfinished at its deadline
NOT RUNThe case did not run

Useful flags

cstudy test flags for practice
FlagEffect
--case IDRun only these cases; repeatable
--allList every case, passing hidden ones included
--time-limit[=VALUE]Turn time limits on. The default gives each case 5 times the reference’s time (5x), with a floor of 100 ms; --time-limit=1500ms sets one limit for every case
--no-time-limitTurn them off, even when your configuration turns them on
--perfAfter every case passes, run a short benchmark and print its verdict
--typecheckTypeScript: also run tsc, since Node’s type stripping does not type-check
--stress NFunction and design problems: also check your code on N generated inputs against a brute-force oracle; concurrent problems: run each stress case N times
--debugWait for your debugger; see Debugging

On a full pass the summary ends with all passed. Next: cstudy done --rating easy|ok|hard. Every run except a debug run is recorded, so cstudy knows whether your latest run passed when you finish.

Hints and solutions

cstudy hint reveals the next hint of the problem. Hints are counted per attempt, and using any caps the grade at ok.

terminal
$ cstudy hint
two-sum · hint 1 of 2
For each value, which partner would complete the sum?

cstudy solution shows, through your pager, the explanation of the optimal approach and its code in your language. Before your attempt has passed, it asks first, because revealing the solution grades the attempt as again:

text
Reveal the solution? The attempt will be graded as again. [y/N]
cstudy solution flags
FlagEffect
--lang LShow the code in another language
--approach IDShow one approach, such as brute-force
--allShow every approach, in ladder order
--explanation-onlyLeave out the code
--broken[=ID]Concurrent problems: show a deliberately broken reference, as a spot-the-bug exercise
--yesSkip the confirmation

Finishing an attempt

cstudy done closes the attempt and schedules the review. When your latest test run passed every case, rate how it went with --rating easy, ok or hard; when it did not, finish with --gave-up. Add --notes "…" to keep a note on the attempt.

terminal
$ cstudy done --rating ok
two-sum · kotlin · passed · 18m 40s · rating ok · hints 0
next review  2026-10-27 (in 3 days) · ease 2.50

The rating becomes a grade, and some things cap it. The lowest cap wins:

How a grade is computed
SituationGrade
Gave up, or revealed the solution before passingagain (0)
Rated easy, ok or hardeasy (3), ok (2), hard (1)
Used a hintat most ok
Finished over the --timer time boxat most hard
Latest benchmark of the attempt is suboptimal, at medium or high confidenceat most hard (turn this off with penalize_suboptimal = false under [schedule])

Solve time is the wall-clock time from cstudy start to cstudy done; there is no pause.

Reviews and spaced repetition

cstudy schedules each problem with a simplified SM-2 algorithm. A good grade pushes the next review further out; a lapse brings the problem back tomorrow. This is how one problem moves through 6 reviews:

A worked review sequence
ReviewGradeNext review inEase after
1ok3 days2.50
2ok7 days2.50
3ok18 days2.50
4hard22 days2.35
5again1 day2.15
6ok3 days2.15

Intervals never exceed 180 days (max_interval_days). A problem counts as mastered once its interval reaches 21 days with a last grade of ok or better, and as due on and after its review date.

What cstudy next picks

cstudy next answers “what should I practise now?” the same way every time for the same progress and date:

  1. A due review, ranked by how overdue it is relative to its interval, plus how weak its pattern is.
  2. Otherwise a new problem from the weakest pattern (or, outside the algorithms track, the weakest track). Within it, easy problems come first; medium opens once you pass an easy one, and hard once you pass a medium one.
  3. Otherwise it prints nothing due and no new problems in scope.
terminal
$ cstudy next
review  merge-intervals  (medium · intervals)  overdue 3d, interval 7d
start   cstudy start merge-intervals --lang kotlin
terminal
$ cstudy next
new     koko-eating-bananas  (medium · binary-search)  weakest pattern: binary-search (0.75)
start   cstudy start koko-eating-bananas --lang kotlin

Weakness combines your recent fail rate, how much of the group you have mastered, and how long ago you last practised it. An untouched group scores 0.75, so cstudy rotates through new patterns before going deep on one.

cstudy next flags
FlagEffect
--track TTracks to pick from, repeatable; default dsa, or next.tracks in your configuration
--pattern POnly problems with this pattern
--difficulty Deasy, medium or hard
--lang LOnly problems available in this language, and start in it
--new / --reviewOnly new problems, or only reviews
--startStart the pick right away

Checking performance

cstudy bench runs your solution and every reference approach on the same generated inputs at growing sizes, fits how the time grows, and compares you with the optimal reference. It checks your answers at every size too.

terminal
$ cstudy bench
two-sum · python · sizes 1e2..1e5 · reps 7 · power AC · load 1.2

TARGET        DECLARED   n=1e2    n=1e3    n=1e4    n=1e5    SLOPE  BAND     MEMORY
brute-force   O(n^2)     0.21ms   19.8ms   2.04s    budget   2.00   ~n^2     constant
hash-map      O(n)       0.01ms   0.09ms   0.94ms   10.1ms   1.00   ~n|nlogn linear
you                      0.01ms   0.11ms   1.10ms   11.8ms   1.01   ~n|nlogn linear

verdict   optimal: matches hash-map, 1.17x at n=1e5 · confidence high (spread 3%, R^2 0.999)
space     linear, same as hash-map · confidence high
history   best previous 13.0ms at n=1e5 (2026-09-12) · now 9% faster · 1st of 3 runs
Bench verdicts
VerdictMeaning
optimalSame growth band as the optimal reference, at most 1.5 times its time at the largest size, and not growing apart
near-optimalSame band, but the ratio grows with n: likely an extra log factor
suboptimalA worse growth band, or over the budget where the optimal reference finished
unknownToo few usable sizes, or no optimal reference in this language

Each verdict comes with a confidence, high, medium or low, and a warning when your machine was busy or on battery. Benchmarks compare you with the references and with your own earlier runs, never with other people.

cstudy bench flags
FlagEffect
--sizes LISTComma-separated input sizes, such as 100,1000,10000
--reps NRepetitions per size (default 7)
--refs-onlyBenchmark only the references; needs no attempt
--no-memorySkip the memory measurement
--lang LThe language of the attempt to benchmark

Note

Concurrent and project problems have no benchmark. See the performance analysis spec for what a slope can and cannot tell.

Timers and mock interviews

Any attempt can have a time box: cstudy start two-sum --timer 25m. cstudy test then shows the time left, and finishing over it caps the grade at hard.

cstudy mock simulates an interview. It picks new medium and hard problems, each from a different group where it can, starts them together with one shared timer, and locks cstudy hint and cstudy solution until the timer ends or every problem is done.

terminal
$ cstudy mock
mock interview · 2 problems · 45 min shared timer · python
1  group-anagrams  (medium · arrays-hashing)  weakest pattern: arrays-hashing (0.75)
   stub       python/practice/group_anagrams.py
   statement  .statements/group-anagrams.md
2  lru-cache  (medium · linked-list)  weakest pattern: linked-list (0.75)
   stub       python/practice/lru_cache.py
   statement  .statements/lru-cache.md
locked     cstudy hint and cstudy solution, until the timer ends or every problem is done
next       cstudy test group-anagrams --watch
cstudy mock flags
FlagEffect
--minutes NThe shared timer (default 45)
--count NHow many problems (default 2)
--track TTracks to pick from, repeatable
--lang LThe language to start them in

In a mock attempt of a project problem, cstudy submit reports only how many hidden cases failed per level, as an interview would.

Tracking progress

cstudy stats summarises your progress per group: problems, attempts, passes, mastered problems, the pass rate of the last 10 attempts, median solve time and weakness. Below come your streak, the reviews due and your latest benchmark verdicts.

terminal
$ cstudy stats
GROUP           PROBLEMS  ATTEMPTED  PASSED  MASTERED  PASS RATE  SOLVE TIME  WEAKNESS
arrays-hashing        17          5       4         1        80%     14m 10s      0.42
two-pointers          10          0       0         0          -           -      0.75
system-design         10          1       1         0       100%     45m 00s      0.30

attempts  6 finished · 5 in the last 7 days · streak 3 days
reviews   1 due today · 1 overdue
bench     4 benched · 2 optimal · 1 near-optimal · 1 suboptimal · 0 unknown

Group by --by pattern (the default), track, lang or difficulty; narrow the attempt columns with --since 2026-10-01; or print --json. To browse problems with their status and next review date, use cstudy list, filtered with --status new|attempted|passed|due|mastered:

terminal
$ cstudy list
ID    SLUG              DIFF    PATTERN          STATUS    DUE         REFS
0001  two-sum           easy    arrays-hashing   passed    2026-10-27  py ts java kt
0002  lru-cache         medium  linked-list      new       -           py ts java kt
0014  koko-eating-...   medium  binary-search    due       2026-10-21  py java

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