Skip to content

qgen — the DSA Question Pipeline

tools/qgen/qgen.py turns a drafted DSA question into a production-ready, fuzz-tested, cross-language-verified markdown file in the website's src/content/. It exists because the failure mode it prevents is embarrassing and real: a reference solution that doesn't pass its own tests — which happened, once, and never again after verify_solution.py became a mandatory gate.

The 10-step model

Steps 1–3 and 9–10 are human; qgen automates 4–8:

#StepWho
1–3decide the question, AI-draft the structured markdown, save to drafts/<slug>.mdyou
4build_tests.sh — compile solutions, run the generator, produce casesqgen
5fix_case_spread.py / trim_oversized_cases.py — balance difficulty spread, trim sizeqgen
6verify_solution.pycross-verify every language's solution against every caseqgen
7lint-content.mjs (the website's copy, via site_config.py)qgen
8move into ediky-website/ediky/src/content/<section>/, audit_sizes.pyqgen
9–10smoke-test in the running site, commityou

Presets: sized to the problem, not one-size

presets.json defines three tiers — matched automatically from the draft's frontmatter topic keywords, overridable by flag:

simplestandardcomplex
generated cases60100120
solution timeout5 s10 s12 s
fuzz iterations1,5005,00010,000
max stdin / expected250 / 100 KB200 / 100 KB400 / 200 KB
post-trim budget150 KB / 40 cases250 KB / 45higher

simple auto-matches topics like string, array, sorting, two pointers, hashing, implementation; unmatched topics get standard. The trim budgets exist because of the sidecar economics in Question Bank — cases users download on Submit should be as small as correctness allows.

What "verified" means here

  • Independent brute-force verifier: the draft includes a second, simpler solution; fuzz.py throws thousands of random inputs at both and diffs outputs. A disagreement fails the pipeline — this catches wrong reference solutions, not just wrong tests.
  • Cross-language: C++17, Python, and Java reference solutions must all pass all cases (langs.py handles per-language compile/run). If Python TLEs where C++ passes, the case sizes (or the per-language multipliers on the website side) are wrong — better to find out here than in production.
  • Adversarial cases: generators are written to include edge patterns (empties, max-N, degenerate structures), not just random noise.

Cross-platform detail that saves an afternoon

The verifiers auto-detect the Python interpreter on Windows (py -3pythonpython3), so the same qgen.py invocation works on the Windows authoring machine and any Unix box without editing scripts.

The screenshot-to-question workflow

A large share of the bank came from real OA screenshots (D.E. Shaw, Flipkart, Okta, Cisco, HackerRank): screenshot → AI-assisted transcription into the structured draft format (statement, constraints, solutions in three languages, generator, brute verifier) → qgen. The pipeline is what makes that workflow trustworthy — a transcription error in constraints or expected behavior gets caught by the brute-force diff instead of shipping.

Failure exit codes

qgen fails loudly with the stage that broke (generation, spread-fix, verification, lint, audit). The most common real failures: a generator emitting out-of-constraint inputs (caught by verify), and oversized cases (caught by audit) — both fixed in the draft, never by loosening the gate.

Ediky Workflow — internal engineering documentation.