Himansh Raj

Striver Judge: My Own Local DSA Judge

· 3 min read

Striver Judge: My Own Local DSA Judge

I wanted to grind the Striver A2Z DSA sheet without living inside a browser tab on someone else's site. So I built Striver Judge, a local judge that renders a problem, lets me write a solution, and compiles and runs my C / C++ against real test cases — on my own machine.

The goal wasn't to clone LeetCode. It was to own the whole loop: the problem statement, the editor, and the grader all running locally, so I could actually understand how a judge works while I solved with it.

Why I made it

Online judges are great until you want to see how the sausage is made. I was curious about the parts you never see: how does a judge take your class Solution and turn it into something it can run and score? Building my own forced me to answer that.

It also gave me a self-contained setup — 462 problems grouped by category with search and difficulty filters, a Monaco editor self-hosted so it works offline, and per-case pass/fail with your output next to the expected one.

How judging actually works

The interesting part is the harness. The Striver dataset is function-signature based — you write a method on a Solution class, not a full program — so the judge has to build the main() for you:

  • Harness mode (C++) — it parses your method signature, binds each test input to a parameter by name or position, and generates a driver that parses inputs, calls your method, and prints the result canonically. It compiles once and runs the binary once per case.
  • It handles scalars, vector<...>, vector<vector<...>>, even TreeNode* / ListNode* by deserializing the dataset's level-order tree and value-array list formats, plus C-array params and auto-derived size arguments.
  • Free-form mode — if your code already has its own main() (always the case for C), it's compiled as-is and fed inputs on stdin.
  • Comparison is lenient — it ignores brackets, commas, and whitespace, compares numbers with tolerance, and normalizes boolean spellings, so trivially-different-but-correct output still passes.

There's also a <bits/stdc++.h> shim injected at compile time so competitive-style includes work on macOS clang.

Running it safely

Since the tool compiles and executes arbitrary C/C++, isolation matters. Execution goes through one script (scripts/judge_exec.py) used by both backends so verdicts match:

  • Docker (production) — a fresh, locked-down container per run: --network none, dropped capabilities, no-new-privileges, and memory / pid / time limits.
  • Local (fallback) — host clang++ when Docker isn't around, with best-effort limits. The Result panel shows a badge (🐳 docker / 💻 local) so I always know which path ran.

Run checks the visible example cases; Submit judges against a full generated answer key when one exists — and there's a generator that produces up to a million constraint-valid cases per problem from a reference solution.

What I learned

  1. Writing a judge teaches you what a judge can't do. Non-unique outputs and exotic signatures were the honest limitations I had to design around, not paper over.
  2. The harness is the hard part. Turning a bare method into a runnable program, for arbitrary types, was far more work than the UI.
  3. Sandboxing isn't optional. The moment you run untrusted code, "it works on my machine" has to mean "and it can't hurt my machine."

If you want to look at the code, here it is: STRIVER-JUDGE on GitHub.