1+ #!/usr/bin/env python3
2+
3+ from dataclasses import dataclass
4+ from os import listdir
5+ from pathlib import Path
6+
7+ import requests
8+
9+
10+ @dataclass
11+ class Task :
12+ """The task dataclass. Container for task info"""
13+
14+ id : str
15+ title : str
16+ solution : str
17+ difficulty : str
18+
19+
20+ def fetch_leetcode_folder_tasks (solutions_folder : Path ) -> list [Task ]:
21+ """Fetch leetcode tasks from the Leetcode"""
22+
23+ # Fetch tasks info from the leetcode API.
24+ resp = requests .get ("https://leetcode.com/api/problems/algorithms/" , timeout = 10 )
25+ content_dict = resp .json ()
26+
27+ raw_tasks_id_dict = {}
28+
29+ for task in content_dict ["stat_status_pairs" ]:
30+ task_stat = task ["stat" ]
31+ raw_tasks_id_dict [str (task_stat ["frontend_question_id" ])] = task
32+
33+ # Generate result tasks info to be inserted into the document
34+ tasks_list = []
35+
36+ difficulty = {1 : "Easy" , 2 : "Medium" , 3 : "Hard" }
37+
38+ for fl in listdir (solutions_folder ):
39+ task_id = fl .split ("." )[0 ]
40+
41+ raw_task = raw_tasks_id_dict .get (task_id , None )
42+ if raw_task is None :
43+ continue
44+
45+ raw_task_stat = raw_task ["stat" ]
46+ tasks_list .append (
47+ Task (
48+ id = f'{ raw_task_stat ["frontend_question_id" ]} ' ,
49+ title = f'[{ raw_task_stat ["question__title" ]} ](https://leetcode.com/problems/{ raw_task_stat ["question__title_slug" ]} )' ,
50+ solution = f"[C++](./src/{ fl } )" ,
51+ difficulty = f'{ difficulty .get (raw_task ["difficulty" ]["level" ], "" )} ' ,
52+ )
53+ )
54+
55+ return tasks_list
56+
57+
58+ HEADER_ID = "#"
59+ HEADER_TITLE = "Title"
60+ HEADER_SOLUTION = "Solution"
61+ HEADER_DIFFICULTY = "Difficulty"
62+ SEPARATOR = "-"
63+
64+
65+ def print_directory_md (tasks_list : list [Task ]) -> None :
66+ """Print tasks into the stdout"""
67+
68+ def get_max_len (get_item ):
69+ return max (list (map (lambda x : len (get_item (x )), tasks_list )))
70+
71+ id_max_length = max (get_max_len (lambda x : x .id ), len (HEADER_ID ))
72+ title_max_length = max (get_max_len (lambda x : x .title ), len (HEADER_TITLE ))
73+ solution_max_length = max (get_max_len (lambda x : x .solution ), len (HEADER_SOLUTION ))
74+ difficulty_max_length = max (
75+ get_max_len (lambda x : x .difficulty ), len (HEADER_DIFFICULTY )
76+ )
77+
78+ def formatted_string (header , title , solution , difficulty ):
79+ return (
80+ f"| { header .rjust (id_max_length )} "
81+ + f"| { title .ljust (title_max_length )} "
82+ + f"| { solution .ljust (solution_max_length )} "
83+ + f"| { difficulty .ljust (difficulty_max_length )} |"
84+ )
85+
86+ tasks_rows = []
87+
88+ tasks_rows .append (
89+ formatted_string (HEADER_ID , HEADER_TITLE , HEADER_SOLUTION , HEADER_DIFFICULTY )
90+ )
91+ tasks_rows .append (
92+ formatted_string (
93+ id_max_length * SEPARATOR ,
94+ title_max_length * SEPARATOR ,
95+ solution_max_length * SEPARATOR ,
96+ difficulty_max_length * SEPARATOR ,
97+ )
98+ )
99+
100+ tasks_list .sort (key = lambda x : int (x .id .strip ()))
101+
102+ for task in tasks_list :
103+ tasks_rows .append (
104+ formatted_string (task .id , task .title , task .solution , task .difficulty )
105+ )
106+
107+ print (
108+ """
109+ # LeetCode
110+
111+ ### LeetCode Algorithm
112+ """
113+ )
114+
115+ for item in tasks_rows :
116+ print (item )
117+
118+
119+ if __name__ == "__main__" :
120+ top_dir = Path ("." )
121+ solutions_folder = top_dir / "leetcode" / "src"
122+
123+ tasks_list = fetch_leetcode_folder_tasks (solutions_folder )
124+ print_directory_md (tasks_list )
0 commit comments