refactor: move DSA notes to org/study_deck_02/

Restructure NeetCode study materials into a dedicated Anki-exportable
deck directory. Separates DSA problem notes from C++ flashcards.

- Move roadmap.org from leetcode/out/ to org/study_deck_02/
- Move 200 note files from org/cpp/dsa/ to org/study_deck_02/dsa/
- Add #+PROPERTY: STUDY_DECK_02 to all org files for org-anki export
- Simplify roadmap format: properties drawer replaces nested headings
- Update NEETCODE backlinks in all note files
- Update extract.mjs and scaffold-notes.mjs for new paths
- Create org/study_deck_02/AGENTS.md with study workflow docs
- Update root and leetcode AGENTS.md
This commit is contained in:
2026-06-01 16:12:21 +08:00
parent 1d88296bf6
commit dfadc1ca48
211 changed files with 2240 additions and 1908 deletions
+8 -6
View File
@@ -43,7 +43,7 @@ and produce byte-identical output.
| `out/roadmap.json` | Full data: graph, all 965 problems, courses |
| `out/roadmap-neetcode150.json` | NeetCode 150 only (199 problems) |
| `out/roadmap.dot` | Graphviz DOT (render with `dot -Tsvg`) |
| `out/roadmap.org` | Org-mode with `TODO` checklists, Python/C++ links |
| `out/roadmap.org` | Org-mode with `TODO` checklists, Python/C++ links (moved to `org/study_deck_02/roadmap.org`) |
| `neetcode-roadmap-graph.json` | Standalone edge list (manual copy) |
| `neetcode-roadmap.dot` | Standalone DOT (manual copy) |
@@ -69,19 +69,21 @@ Arrays & Hashing
Each topic is a `* TODO` heading with a `[/]` cookie for progress.
Problems are `** TODO` sub-headings with difficulty tags (`:easy:`,
`:medium:`, `:hard:`). Python and C++ solution links are `***` sub-headings
under each problem. Each problem also links to a notes file at
`org/cpp/dsa/<topic>/<problem>.org` for personal solutions and flashcards.
`:medium:`, `:hard:`). Each problem has a properties drawer with links
to LeetCode, GitHub solutions (Python/C++), and video. A `Notes:` line
links to the personal notes file at
`org/study_deck_02/dsa/<topic>/<problem>.org`.
### Notes Files
`org/cpp/dsa/<topic>/<code>.org` — one per NeetCode 150 problem (199 total).
`org/study_deck_02/dsa/<topic>/<code>.org` — one per NeetCode 150 problem (199 total).
Scaffolded by `scaffold-notes.mjs`. Template:
```org
* TODO 0217. Contains Duplicate :easy:
#+PROPERTY: STUDY_DECK_02
:PROPERTIES:
:NEETCODE: [[../../../../leetcode/out/roadmap.org::*0217. Contains Duplicate][Roadmap]]
:NEETCODE: [[../../roadmap.org::*0217. Contains Duplicate][Roadmap]]
:END:
#+begin_src cpp
+15 -12
View File
@@ -197,6 +197,7 @@ function buildOrg(sortedNodes, problemsByTopic) {
const now = new Date().toISOString().slice(0, 10);
lines.push("#+TITLE: NeetCode Roadmap");
lines.push("#+PROPERTY: STUDY_DECK_02");
lines.push(`#+DATE: ${now}`);
lines.push("#+TODO: TODO DONE");
lines.push("#+STARTUP: overview");
@@ -213,7 +214,7 @@ function buildOrg(sortedNodes, problemsByTopic) {
.replace(/[^a-z0-9]+/g, "-")
.replace(/(^-|-$)/g, "");
const notesRoot = "../../org/cpp/dsa";
const notesRoot = "dsa";
for (const node of sortedNodes) {
const topicProblems = (problemsByTopic[node.name] || []).filter(
@@ -234,17 +235,17 @@ function buildOrg(sortedNodes, problemsByTopic) {
const lcUrl = `${LEETCODE_BASE}${p.link}`;
const num = p.code.split("-")[0];
const notesFile = `${notesRoot}/${slug}/${p.code}.org`;
lines.push(`** TODO ${num}. ${p.name} :${tag}: [/]`);
lines.push(`*** TODO Python`);
lines.push(`- [[${GITHUB_SOLUTIONS}python/${p.code}.py][${p.code}.py]]`);
lines.push(`*** TODO C++`);
lines.push(`- [[${GITHUB_SOLUTIONS}cpp/${p.code}.cpp][${p.code}.cpp]]`);
lines.push(`- LeetCode: [[${lcUrl}][${p.link}]]`);
lines.push(`** TODO ${num}. ${p.name} :${tag}:`);
lines.push(`:PROPERTIES:`);
lines.push(`:LEETCODE: [[${lcUrl}][Problem]]`);
lines.push(`:CPP: [[${GITHUB_SOLUTIONS}cpp/${p.code}.cpp][Solution]]`);
lines.push(`:PYTHON: [[${GITHUB_SOLUTIONS}python/${p.code}.py][Solution]]`);
if (p.video)
lines.push(
`- Video: [[https://youtube.com/watch?v=${p.video}][explanation]]`
`:VIDEO: [[https://youtube.com/watch?v=${p.video}][Watch]]`
);
lines.push(`- Notes: [[${notesFile}][My Solution]]`);
lines.push(`:END:`);
lines.push(`Notes: [[${notesFile}][My Solution]]`);
}
lines.push("");
}
@@ -343,9 +344,11 @@ async function main() {
// DOT
writeFileSync(join(outDir, "roadmap.dot"), buildDot(nodes), "utf8");
// Org-mode
// Org-mode — write to org/study_deck_02/roadmap.org
const orgDir = join(__dirname, "../org/study_deck_02");
mkdirSync(orgDir, { recursive: true });
writeFileSync(
join(outDir, "roadmap.org"),
join(orgDir, "roadmap.org"),
buildOrg(sorted, problemsByTopic),
"utf8"
);
@@ -353,7 +356,7 @@ async function main() {
console.log(`Wrote ${outDir}/roadmap.json (${result.stats.totalProblems} problems total)`);
console.log(`Wrote ${outDir}/roadmap-neetcode150.json (${result.stats.neetcode150} problems)`);
console.log(`Wrote ${outDir}/roadmap.dot`);
console.log(`Wrote ${outDir}/roadmap.org`);
console.log(`Wrote ${join(orgDir, "roadmap.org")}`);
console.log(
` ${result.stats.topics} topics, ${result.stats.edges} edges`
);
+1 -1
View File
@@ -1,6 +1,6 @@
{
"source": "https://neetcode.io/roadmap",
"extracted": "2026-05-31",
"extracted": "2026-06-01",
"graph": {
"nodes": [
{
+1 -1
View File
@@ -1,6 +1,6 @@
{
"source": "https://neetcode.io/roadmap",
"extracted": "2026-05-31",
"extracted": "2026-06-01",
"graph": {
"nodes": [
{
File diff suppressed because it is too large Load Diff
+5 -4
View File
@@ -4,8 +4,8 @@ import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const roadmap = readFileSync(join(__dirname, "out/roadmap.org"), "utf8");
const dsaDir = join(__dirname, "../org/cpp/dsa");
const roadmap = readFileSync(join(__dirname, "../org/study_deck_02/roadmap.org"), "utf8");
const dsaDir = join(__dirname, "../org/study_deck_02/dsa");
const topicSlug = (name) =>
name
@@ -24,7 +24,7 @@ for (const line of roadmap.split("\n")) {
}
const problemMatch = line.match(
/^\*\* TODO (\d+)\. (.+?) :(easy|medium|hard): \[\/\]$/
/^\*\* TODO (\d+)\. (.+?) :(easy|medium|hard):/
);
if (problemMatch) {
const [, num, name, diff] = problemMatch;
@@ -37,8 +37,9 @@ for (const line of roadmap.split("\n")) {
if (existsSync(filePath)) continue;
const relPath = `../../../../leetcode/out/roadmap.org::*${num}. ${name}`;
const relPath = `../../roadmap.org::*${num}. ${name}`;
const content = `* TODO ${num}. ${name} :${diff}:
#+PROPERTY: STUDY_DECK_02
:PROPERTIES:
:NEETCODE: [[${relPath}][Roadmap]]
:END: