Skip to content

Commit 9e6a7c1

Browse files
chore(ci): scaffolding script
1 parent fc93cf3 commit 9e6a7c1

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

scripts/scaffolding.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import os
2+
import json
3+
import re
4+
import sys
5+
import time
6+
import requests
7+
8+
GRAPHQL_URL = "https://leetcode.com/graphql"
9+
10+
def to_slug(name: str) -> str:
11+
slug = name.lower()
12+
slug = re.sub(r"[^a-z0-9 \-]+", "", slug)
13+
slug = slug.replace(" ", "-")
14+
slug = re.sub(r"-+", "-", slug)
15+
return slug
16+
17+
def fetch_problem_details(name: str) -> dict:
18+
title_slug = to_slug(name)
19+
query = """
20+
query getQuestionDetail($titleSlug: String!) {
21+
question(titleSlug: $titleSlug) {
22+
questionId
23+
title
24+
titleSlug
25+
difficulty
26+
topicTags { name }
27+
}
28+
}
29+
"""
30+
variables = {"titleSlug": title_slug}
31+
response = requests.post(GRAPHQL_URL, json={"query": query, "variables": variables},
32+
headers={"Content-Type": "application/json"})
33+
response.raise_for_status()
34+
data = response.json()
35+
if "errors" in data:
36+
raise Exception(data["errors"])
37+
q = data["data"]["question"]
38+
return {
39+
"id": q["questionId"],
40+
"title": q["title"],
41+
"slug": q["titleSlug"],
42+
"difficulty": q["difficulty"],
43+
"tags": [t["name"] for t in q.get("topicTags", [])]
44+
}
45+
46+
def normalize_filename(problem_id, title, ext=".py"):
47+
safe = re.sub(r'[^a-z0-9]', '_', title.lower())
48+
safe = re.sub(r'_+', '_', safe).strip('_')
49+
return f"lc_{str(problem_id).zfill(4)}_{safe}{ext}"
50+
51+
def create_problem_file(base_dir: str, problem: dict):
52+
os.makedirs(base_dir, exist_ok=True)
53+
filepath = os.path.join(base_dir, normalize_filename(problem["id"], problem["title"]))
54+
if not os.path.exists(filepath):
55+
with open(filepath, "w", encoding="utf-8") as f:
56+
f.write(f"# {problem['title']} (https://leetcode.com/problems/{problem['slug']}/)\n")
57+
f.write(f"# Difficulty: {problem['difficulty']}\n")
58+
if problem.get("tags"):
59+
f.write(f"# Tags: {', '.join(problem['tags'])}\n")
60+
return filepath
61+
62+
def main():
63+
if len(sys.argv) < 2:
64+
print("Usage: python leetcode_scaffold.py <input_names.json>")
65+
sys.exit(1)
66+
67+
input_file = sys.argv[1]
68+
group_name = os.path.splitext(os.path.basename(input_file))[0]
69+
70+
root_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
71+
base_repo = os.path.join(root_dir, "problems", group_name)
72+
73+
with open(input_file, encoding="utf-8") as f:
74+
problem_names = json.load(f)["problems"]
75+
76+
problems = []
77+
for name in problem_names:
78+
try:
79+
problems.append(fetch_problem_details(name))
80+
time.sleep(0.2)
81+
except Exception as e:
82+
print(f"Error fetching '{name}': {e}")
83+
84+
os.makedirs(base_repo, exist_ok=True)
85+
# details_file = os.path.join(base_repo, f"{group_name}-details.json")
86+
details_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), f"{group_name}-details.json")
87+
with open(details_file, "w", encoding="utf-8") as f:
88+
json.dump(problems, f, indent=2)
89+
90+
for problem in problems:
91+
create_problem_file(base_repo, problem)
92+
93+
print(f"Scaffolding completed: {len(problems)} problems in {base_repo}")
94+
print(f"Details saved in: {details_file}")
95+
96+
if __name__ == "__main__":
97+
main()

0 commit comments

Comments
 (0)