LeetCode几乎成了如今每一个人找工做前都要刷的"新手村"的怪,每个找工做的人面试以前都要都会去刷一刷。闲话很少说,先看看大佬们都是怎么评价LeetCodejavascript
虽然面试官也不会看你github上leetcode的repo,可是若是你有这么一个东西仍是极好的,不少大佬都会去刷这个东西,放在github上面,固然新手也会这么作。咱们就会发现,大佬们的README超级好看,方便本身往后查找,可是新手的命名就比较杂乱无章,一点也不规范,本身找起来很是费劲。我本身就是这么一个状况,因此我决定重构一下这个目录结构,生成一个好看一点的。java
咱们先看一下生成的效果吧!更详细具体效果请查看这里python
在github上建立一个仓库,好比叫leetcode或者像个人同样叫algorithms_and_oj。而后从github中git clone下来。c++
而后,安装项目前置须要的库:git
pip install requests
复制代码
首先须要配置咱们的路径 (如下路径均按照我项目来配置,须要按照本身要求修改)github
class Config:
""" some config, such as your github page 这里须要配置你本身的项目地址 1. 本地仓库的的路径 2. github中的仓库leetcode解法的路径 """
local_path = '/home/yuan/PycharmProjects/algorithms_and_oj'
# solution of leetcode
github_leetcode_url = 'https://github.com/hey-bruce/algorithms_and_oj/blob/master/leetcode-algorithms/'
# solution of pat, 暂时还没用上
github_pat_url = 'https://github.com/hey-bruce/algorithms_and_oj/blob/master/pat-algorithms/'
leetcode_url = 'https://leetcode.com/problems/'
复制代码
咱们须要哪些信息,每一个问题的ID,title, url,难度,已经使用什么语言解决等,因此咱们很天然的构造一个Question类面试
class Question:
""" this class used to store the inform of every question """
def __init__(self, id_, name, url, lock, difficulty):
self.id_ = id_
self.title = name
# the problem description url 问题描述页
self.url = url
self.lock = lock # boolean,锁住了表示须要购买
self.difficulty = difficulty
# the solution url
self.python = ''
self.java = ''
self.javascript = ''
self.c_plus_plus = ''
def __repr__(self):
""" 没啥用,我为了调试方便写的 :return: """
return str(self.id_) + ' ' + str(self.title) + ' ' + str(self.url)
复制代码
接下来,咱们就要从LeetCode上获取问题,在在google一查,就找到了https://leetcode.com/api/problems/algorithms/返回的是json数据。稍微进行了一下分析(这个本身看一下数据,很容易发现的,虽然leetcode没有api描述页),就能够知道stat
中的frontend_question_id
是id
,question__title_slug
对应的url
的地址,question__title
对应的是问题的名字,paid_only
表示是否须要购买。difficulty
表示难度.。而后咱们能够出获取LeetCode信息的代码。编程
def get_leetcode_problems(self):
""" used to get leetcode inform :return: """
# we should look the response data carefully to find law
# return byte. content type is byte
content = requests.get('https://leetcode.com/api/problems/algorithms/').content
# get all problems
self.questions = json.loads(content)['stat_status_pairs']
# print(self.questions)
difficultys = ['Easy', 'Medium', 'Hard']
for i in range(len(self.questions) - 1, -1, -1):
question = self.questions[i]
name = question['stat']['question__title']
url = question['stat']['question__title_slug']
id_ = str(question['stat']['frontend_question_id'])
if int(id_) < 10:
id_ = '00' + id_
elif int(id_) < 100:
id_ = '0' + id_
lock = question['paid_only']
if lock:
self.locked += 1
difficulty = difficultys[question['difficulty']['level'] - 1]
url = Config.leetcode_url + url + '/description/'
q = Question(id_, name, url, lock, difficulty)
# 这里后面咱们会放到类里面,因此不用担忧
# 之因此用一个table和table_item就是由于,咱们后期已经用什么语言解决题目的时候要进行索引
self.table.append(q.id_)
self.table_item[q.id_] = q
return self.table, self.table_item
复制代码
咱们须要一个东西记录咱们完成状况的类CompleteInform:json
class CompleteInform:
""" this is statistic inform, 用每种语言完成了多少题 """
def __init__(self):
self.solved = {
'python': 0,
'c++': 0,
'java': 0,
'javascript': 0
}
self.total = 0
def __repr__(self):
return str(self.solved)
复制代码
而后咱们根据题目信息来创建题目对应的文件夹,api
def __create_folder(self, oj_name):
""" oj_name后面会传入'leetcode',这里这么作就是后期,我想扩展生成别的oj的table """
oj_algorithms = Config.local_path + '/' + oj_name + '-algorithms'
if os.path.exists(oj_algorithms):
print(oj_name, ' algorithms is already exits')
else:
print('creating {} algorithms....'.format(oj_name))
os.mkdir(oj_algorithms)
for item in self.table_item.values():
question_folder_name = oj_algorithms + '/' + item.id_ + '. ' + item.title
if not os.path.exists(question_folder_name):
print(question_folder_name + 'is not exits, create it now....')
os.mkdir(question_folder_name)
# 这里都会传入一个‘leetcode',设置oj名字就是为了方便扩展
def update_table(self, oj):
# the complete inform should be update
complete_info = CompleteInform()
self.get_leetcode_problems()
# the total problem nums
complete_info.total = len(self.table)
self.__create_folder(oj)
oj_algorithms = Config.local_path + '/' + oj + '-algorithms'
# 查看os.walk看具体返回的是什么东西
for _, folders, _ in os.walk(oj_algorithms):
for folder in folders:
for _, _, files in os.walk(os.path.join(oj_algorithms, folder)):
if len(files) != 0:
complete_info.complete_num += 1
for item in files:
if item.endswith('.py'):
# 这个部分能够写成函数,不过我好像设计有点问题,不太好重构,请读者本身思考
complete_info.solved['python'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].python = '[python]({})'.format(folder_url)
elif item.endswith('.java'):
complete_info.solved['java'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].java = '[Java]({})'.format(folder_url)
elif item.endswith('.cpp'):
complete_info.solved['c++'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].c_plus_plus = '[C++]({})'.format(folder_url)
elif item.endswith('.js'):
complete_info.solved['javascript'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].javascript = '[JavaScript]({})'.format(folder_url)
# 这里使用到的Readme这个类就是写文件,相对不是特别重要,没什么好讲的
readme = Readme(complete_info.total, complete_info.complete_num, complete_info.solved)
readme.create_leetcode_readme([self.table, self.table_item])
print('-------the complete inform-------')
print(complete_info.solved)
复制代码
上面需用用到的Readme类,用来生成README.md,只是进行了文件的读写,相对比较简单。聪明的你确定一看就知道了。(只须要了解一点markdown中表格的生成规则)
class Readme:
""" generate folder and markdown file update README.md when you finish one problem by some language """
def __init__(self, total, solved, others):
""" :param total: total problems nums :param solved: solved problem nums :param others: 暂时还没用,我想作扩展 """
self.total = total
self.solved = solved
self.others = others
self.time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.msg = '# Keep thinking, keep alive\n' \
'Until {}, I have solved **{}** / **{}** problems. ' \
'\n\nCompletion statistic: ' \
'\n1. JavaScript: {javascript} ' \
'\n2. Python: {python}' \
'\n3. C++: {c++}' \
'\n4. Java: {java}' \
'\n\nNote: :lock: means you need to buy a book from LeetCode\n'.format(
self.time, self.solved, self.total, **self.others)
def create_leetcode_readme(self, table_instance):
""" create REAdME.md :return: """
file_path = Config.local_path + '/README.md'
# write some basic inform about leetcode
with open(file_path, 'w') as f:
f.write(self.msg)
f.write('\n----------------\n')
with open(file_path, 'a') as f:
f.write('## LeetCode Solution Table\n')
f.write('| ID | Title | Difficulty | JavaScript | Python | C++ | Java |\n')
f.write('|:---:' * 7 + '|\n')
table, table_item = table_instance
for index in table:
item = table_item[index]
if item.lock:
_lock = ':lock:'
else:
_lock = ''
data = {
'id': item.id_,
'title': '[{}]({}) {}'.format(item.title, item.url, _lock),
'difficulty': item.difficulty,
'js': item.javascript if item.javascript else 'To Do',
'python': item.python if item.python else 'To Do',
'c++': item.c_plus_plus if item.c_plus_plus else 'To Do',
'java': item.java if item.java else 'To Do'
}
line = '|{id}|{title}|{difficulty}|{js}|{python}|{c++}|{java}|\n'.format(**data)
f.write(line)
print('README.md was created.....')
复制代码
完整代码请看:(这个能够跑,欢迎使用)
#!/usr/bin/env python
# Created by Bruce yuan on 18-1-22.
import requests
import os
import json
import time
class Config:
""" some config, such as your github page 这里须要配置你本身的项目地址 1. 本地仓库的的路径 2. github中的仓库leetcode解法的路径 """
local_path = '/home/yuan/PycharmProjects/algorithms_and_oj'
# solution of leetcode
github_leetcode_url = 'https://github.com/hey-bruce/algorithms_and_oj/blob/master/leetcode-algorithms/'
# solution of pat, 暂时还没写
github_pat_url = 'https://github.com/hey-bruce/algorithms_and_oj/blob/master/pat-algorithms/'
leetcode_url = 'https://leetcode.com/problems/'
class Question:
""" this class used to store the inform of every question """
def __init__(self, id_, name, url, lock, difficulty):
self.id_ = id_
self.title = name
# the problem description url 问题描述页
self.url = url
self.lock = lock # boolean,锁住了表示须要购买
self.difficulty = difficulty
# the solution url
self.python = ''
self.java = ''
self.javascript = ''
self.c_plus_plus = ''
def __repr__(self):
""" 没啥用,我为了调试方便写的 :return: """
return str(self.id_) + ' ' + str(self.title) + ' ' + str(self.url)
class TableInform:
def __init__(self):
# raw questions inform
self.questions = []
# this is table index
self.table = []
# this is the element of question
self.table_item = {}
self.locked = 0
def get_leetcode_problems(self):
""" used to get leetcode inform :return: """
# we should look the response data carefully to find law
# return byte. content type is byte
content = requests.get('https://leetcode.com/api/problems/algorithms/').content
# get all problems
self.questions = json.loads(content)['stat_status_pairs']
# print(self.questions)
difficultys = ['Easy', 'Medium', 'Hard']
for i in range(len(self.questions) - 1, -1, -1):
question = self.questions[i]
name = question['stat']['question__title']
url = question['stat']['question__title_slug']
id_ = str(question['stat']['frontend_question_id'])
if int(id_) < 10:
id_ = '00' + id_
elif int(id_) < 100:
id_ = '0' + id_
lock = question['paid_only']
if lock:
self.locked += 1
difficulty = difficultys[question['difficulty']['level'] - 1]
url = Config.leetcode_url + url + '/description/'
q = Question(id_, name, url, lock, difficulty)
self.table.append(q.id_)
self.table_item[q.id_] = q
return self.table, self.table_item
# create problems folders
def __create_folder(self, oj_name):
oj_algorithms = Config.local_path + '/' + oj_name + '-algorithms'
if os.path.exists(oj_algorithms):
print(oj_name, ' algorithms is already exits')
else:
print('creating {} algorithms....'.format(oj_name))
os.mkdir(oj_algorithms)
for item in self.table_item.values():
question_folder_name = oj_algorithms + '/' + item.id_ + '. ' + item.title
if not os.path.exists(question_folder_name):
print(question_folder_name + 'is not exits, create it now....')
os.mkdir(question_folder_name)
def update_table(self, oj):
# the complete inform should be update
complete_info = CompleteInform()
self.get_leetcode_problems()
# the total problem nums
complete_info.total = len(self.table)
complete_info.lock = self.locked
self.__create_folder(oj)
oj_algorithms = Config.local_path + '/' + oj + '-algorithms'
# 查看os.walk看具体返回的是什么东西
for _, folders, _ in os.walk(oj_algorithms):
for folder in folders:
for _, _, files in os.walk(os.path.join(oj_algorithms, folder)):
# print(files)
if len(files) != 0:
complete_info.complete_num += 1
for item in files:
if item.endswith('.py'):
complete_info.solved['python'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].python = '[Python]({})'.format(folder_url)
elif item.endswith('.java'):
complete_info.solved['java'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].java = '[Java]({})'.format(folder_url)
elif item.endswith('.cpp'):
complete_info.solved['c++'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].c_plus_plus = '[C++]({})'.format(folder_url)
elif item.endswith('.js'):
complete_info.solved['javascript'] += 1
folder_url = folder.replace(' ', "%20")
folder_url = os.path.join(folder_url, item)
folder_url = os.path.join(Config.github_leetcode_url, folder_url)
self.table_item[folder[:3]].javascript = '[JavaScript]({})'.format(folder_url)
readme = Readme(complete_info.total,
complete_info.complete_num,
complete_info.lock,
complete_info.solved)
readme.create_leetcode_readme([self.table, self.table_item])
print('-------the complete inform-------')
print(complete_info.solved)
class CompleteInform:
""" this is statistic inform """
def __init__(self):
self.solved = {
'python': 0,
'c++': 0,
'java': 0,
'javascript': 0
}
self.complete_num = 0
self.lock = 0
self.total = 0
def __repr__(self):
return str(self.solved)
class Readme:
""" generate folder and markdown file update README.md when you finish one problem by some language """
def __init__(self, total, solved, locked, others):
""" :param total: total problems nums :param solved: solved problem nums :param others: 暂时还没用,我想作扩展 """
self.total = total
self.solved = solved
self.others = others
self.locked = locked
self.time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.msg = '# Keep thinking, keep alive\n' \
'Until {}, I have solved **{}** / **{}** problems ' \
'while **{}** are still locked.' \
'\n\nCompletion statistic: ' \
'\n1. JavaScript: {javascript} ' \
'\n2. Python: {python}' \
'\n3. C++: {c++}' \
'\n4. Java: {java}' \
'\n\nNote: :lock: means you need to buy a book from LeetCode\n'.format(
self.time, self.solved, self.total, self.locked, **self.others)
def create_leetcode_readme(self, table_instance):
""" create REAdME.md :return: """
file_path = Config.local_path + '/README.md'
# write some basic inform about leetcode
with open(file_path, 'w') as f:
f.write(self.msg)
f.write('\n----------------\n')
with open(file_path, 'a') as f:
f.write('## LeetCode Solution Table\n')
f.write('| ID | Title | Difficulty | JavaScript | Python | C++ | Java |\n')
f.write('|:---:' * 7 + '|\n')
table, table_item = table_instance
for index in table:
item = table_item[index]
if item.lock:
_lock = ':lock:'
else:
_lock = ''
data = {
'id': item.id_,
'title': '[{}]({}) {}'.format(item.title, item.url, _lock),
'difficulty': item.difficulty,
'js': item.javascript if item.javascript else 'To Do',
'python': item.python if item.python else 'To Do',
'c++': item.c_plus_plus if item.c_plus_plus else 'To Do',
'java': item.java if item.java else 'To Do'
}
line = '|{id}|{title}|{difficulty}|{js}|{python}|{c++}|{java}|\n'.format(**data)
f.write(line)
print('README.md was created.....')
def main():
table = TableInform()
table.update_table('leetcode')
if __name__ == '__main__':
main()
复制代码
欢迎使用,欢迎star,Happy Coding!
做者:BBruceyuan(袁朝发)
Github:github.com/bbruceyuan
知乎专栏:打点酱油
简书地址:打点酱油
微信公众号:动手学编程