Skip to content

Commit 21e9a45

Browse files
committed
Time: 1 ms (95.81%), Space: 17.9 MB (25.52%) - LeetHub
1 parent ebdf108 commit 21e9a45

File tree

88 files changed

+364
-322
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+364
-322
lines changed

.github/workflows/leethub.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ jobs:
1717
- name: Move questions to leetcode directory
1818
run: python3 .github/workflows/scripts/leethub_support.py
1919

20-
- name: Run autopep8
20+
- name: Format python answers
2121
run: |
22-
pip3 install autopep8
23-
autopep8 -i -r leetcode
22+
python3 -m pip install --upgrade pip
23+
pip install ruff
24+
ruff format **/*.py
2425
2526
- name: Format go answers
2627
run: .github/workflows/scripts/go_handler.sh

.github/workflows/scripts/leethub_support.py

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,24 @@
22
Move the directories generated by [LeetHub](https://github.com/QasimWani/LeetHub)
33
to the 'leetcode' directory, with the question number is added as prefix.
44
"""
5+
56
import json
67
import logging
78
import re
89
import shutil
910
from pathlib import Path
1011
from typing import List, Dict
1112

12-
WORKDIR = Path('.')
13-
EXCLUDED = ['codility', 'leetcode', 'others']
14-
TARGET_DIRECTORY = WORKDIR / 'leetcode'
15-
SCRIPTS_DIRECTORY = WORKDIR / '.github/workflows/scripts'
16-
EXISTING_QUESTIONS = list(TARGET_DIRECTORY.glob('*'))
13+
WORKDIR = Path(".")
14+
EXCLUDED = ["codility", "leetcode", "others"]
15+
TARGET_DIRECTORY = WORKDIR / "leetcode"
16+
SCRIPTS_DIRECTORY = WORKDIR / ".github/workflows/scripts"
17+
EXISTING_QUESTIONS = list(TARGET_DIRECTORY.glob("*"))
1718

1819
# icons are provided by [devicon](https://devicon.dev).
19-
ICONS = json.loads((SCRIPTS_DIRECTORY / 'lang_suffix_to_icon.json').read_bytes())
20+
ICONS = json.loads((SCRIPTS_DIRECTORY / "lang_suffix_to_icon.json").read_bytes())
2021

21-
QUESTION_BASE_URL = 'https://leetcode.com/problems'
22+
QUESTION_BASE_URL = "https://leetcode.com/problems"
2223

2324

2425
class Question:
@@ -29,58 +30,62 @@ def __init__(self, path: Path):
2930
if self.path.is_file():
3031
raise ValueError(f"{self.path.as_posix()} should be a directory")
3132

32-
self.readme_path: Path = self.path / 'README.md'
33+
self.readme_path: Path = self.path / "README.md"
3334
if self.is_in_target_directory and not self.readme_path.exists():
3435
raise ValueError(f"{self.readme_path.as_posix()} does not exist")
3536

3637
# handle metadata
37-
self.tag: str = ''
38+
self.tag: str = ""
3839
self.number: int = 0
39-
self.title: str = 'N/A'
40-
self.difficulty: str = 'N/A'
40+
self.title: str = "N/A"
41+
self.difficulty: str = "N/A"
4142
self._init_question_meta()
4243

4344
def _init_question_meta(self):
4445
if self.readme_path.exists():
4546
self._parse_meta_from_md()
4647
return
4748

48-
splited_tag = self.path.name.split('_')
49+
splited_tag = self.path.name.split("_")
4950
if len(splited_tag) == 2:
5051
self.tag = splited_tag[-1]
5152
elif len(splited_tag) == 1:
52-
self.tag = '-'.join(self.path.name.split('-')[1:])
53+
self.tag = "-".join(self.path.name.split("-")[1:])
5354
else:
54-
raise ValueError(f'Cannot parse question tag for {self.path}')
55+
raise ValueError(f"Cannot parse question tag for {self.path}")
5556

56-
existing_dirs = list(TARGET_DIRECTORY.glob(f'*_{self.tag}'))
57+
existing_dirs = list(TARGET_DIRECTORY.glob(f"*_{self.tag}"))
5758
if len(existing_dirs) == 0:
58-
raise ValueError(f'Cannot find readme of {self.tag}')
59+
raise ValueError(f"Cannot find readme of {self.tag}")
5960
if len(existing_dirs) > 1:
60-
raise ValueError(f"Multiple existing readme of {self.tag} are found: {existing_dirs}. "
61-
"Manually deleting duplicated ones may be required.")
62-
existing_md = existing_dirs[0] / 'README.md'
61+
raise ValueError(
62+
f"Multiple existing readme of {self.tag} are found: {existing_dirs}. "
63+
"Manually deleting duplicated ones may be required."
64+
)
65+
existing_md = existing_dirs[0] / "README.md"
6366
self._parse_meta_from_md(existing_md)
6467

6568
def _parse_meta_from_md(self, path: Path = None):
6669
path = path if path else self.readme_path
67-
pattern: str = r'^<h2><a href="https://leetcode\.com/problems/(.*)[//]+">(\d+)\. (.*)</a></h2><h3>(.*)</h3>.*'
70+
pattern: str = r'^<h2><a href="https://leetcode\.com/problems/(.*?)[/]*">(\d+)\. (.*)</a></h2><h3>(.*)</h3>.*'
6871
matched: re.Match = re.search(pattern, path.read_text())
6972
if matched:
7073
self.tag = matched.groups()[0]
7174
self.number = int(matched.groups()[1])
7275
self.title = matched.groups()[2]
7376
self.difficulty = matched.groups()[3]
7477
else:
75-
logging.warning(f'Failed to parse metadata from question readme from "{self.path}"')
78+
logging.warning(
79+
f'Failed to parse metadata from question readme from "{self.path}"'
80+
)
7681

7782
def move_to_target_directory(self):
7883
if self.is_in_target_directory:
7984
return
8085

8186
dest_directory = TARGET_DIRECTORY / self.folder_name
8287
if dest_directory.exists():
83-
for src in self.path.glob('*'):
88+
for src in self.path.glob("*"):
8489
dest = dest_directory / src.name
8590
if dest.exists():
8691
dest.unlink()
@@ -101,7 +106,7 @@ def solutions_dict(self) -> Dict[str, Path]:
101106
solutions: Dict[str, Path] = {} # ext as dict key
102107
for sol in self.path.glob(f"*{self.tag}.*"):
103108
solutions[sol.suffix] = sol
104-
return solutions
109+
return {k: v for k, v in sorted(solutions.items())}
105110

106111
@property
107112
def folder_name(self) -> str:
@@ -114,28 +119,33 @@ def link(self) -> str:
114119

115120
def move_question_directory():
116121
logging.info(f"Moving submitted solutions to {TARGET_DIRECTORY}...")
117-
for path in WORKDIR.glob('*'):
122+
for path in WORKDIR.glob("*"):
118123
if path.is_file():
119124
continue
120-
if path.name in EXCLUDED or path.name.startswith('.'):
125+
if path.name in EXCLUDED or path.name.startswith("."):
121126
continue
122127
try:
123128
q = Question(path)
124129
q.move_to_target_directory()
125130
except Exception as error:
126-
logging.warning(f'Somthing went wrong when moving directory "{path}", error={error}')
131+
logging.warning(
132+
f'Somthing went wrong when moving directory "{path}", error={error}'
133+
)
127134

128135

129136
def build_readme(questions: List[Question]) -> str:
130-
md = "| # | Title | Solutions | Difficulty |\n" + \
131-
"| - | - | - | - |\n"
137+
md = "| # | Title | Solutions | Difficulty |\n" + "| - | - | - | - |\n"
132138
for q in questions:
133139
anchored_title = f"[{q.title}]({q.link})"
134140
solution_links = ""
135141
for ext, path in q.solutions_dict.items():
136-
solution_links += f'<a href="{path}"><img src="{ICONS[ext]}" width="20" height="20"></a>'
137-
md += f"| {q.number} | {anchored_title} " + \
138-
f"| {solution_links} | {q.difficulty} |\n"
142+
solution_links += (
143+
f'<a href="{path}"><img src="{ICONS[ext]}" width="20" height="20"></a>'
144+
)
145+
md += (
146+
f"| {q.number} | {anchored_title} "
147+
+ f"| {solution_links} | {q.difficulty} |\n"
148+
)
139149
return md
140150

141151

@@ -144,9 +154,9 @@ def build_readme(questions: List[Question]) -> str:
144154
move_question_directory()
145155

146156
questions = []
147-
level_count = {'easy': 0, 'medium': 0, 'hard': 0}
157+
level_count = {"easy": 0, "medium": 0, "hard": 0}
148158
total = 0
149-
for path in TARGET_DIRECTORY.glob('*'):
159+
for path in TARGET_DIRECTORY.glob("*"):
150160
q = Question(path)
151161
questions.append(q)
152162
if q.difficulty.lower() not in level_count:
@@ -157,8 +167,10 @@ def build_readme(questions: List[Question]) -> str:
157167
logging.info(f"{total} questions are found ({level_count})")
158168

159169
md_table = build_readme(questions)
160-
with open(SCRIPTS_DIRECTORY / 'README.md.tpl', 'r') as template, \
161-
open('README.md', 'w') as output:
170+
with (
171+
open(SCRIPTS_DIRECTORY / "README.md.tpl", "r") as template,
172+
open("README.md", "w") as output,
173+
):
162174
template_string = template.read()
163175
content = template_string.format(leetcode=md_table, total=total, **level_count)
164176
output.write(content)

0 commit comments

Comments
 (0)