diff --git a/solution/0500-0599/0547.Number of Provinces/Solution.py b/solution/0500-0599/0547.Number of Provinces/Solution.py
index 6ff12cd515..f076345dfa 100644
--- a/solution/0500-0599/0547.Number of Provinces/Solution.py
+++ b/solution/0500-0599/0547.Number of Provinces/Solution.py
@@ -3,9 +3,9 @@ class Solution:
def dfs(i: int):
vis[i] = True
for j, x in enumerate(isConnected[i]):
- if not vis[j] and x:
+ if not vis[j] and x:
dfs(j)
-
+
n = len(isConnected)
vis = [False] * n
ans = 0
@@ -13,4 +13,4 @@ class Solution:
if not vis[i]:
dfs(i)
ans += 1
- return ans
\ No newline at end of file
+ return ans
diff --git a/solution/0800-0899/0887.Super Egg Drop/Solution.py b/solution/0800-0899/0887.Super Egg Drop/Solution.py
index 4ccba265b8..676d3170fc 100644
--- a/solution/0800-0899/0887.Super Egg Drop/Solution.py
+++ b/solution/0800-0899/0887.Super Egg Drop/Solution.py
@@ -17,4 +17,4 @@ class Solution:
r = mid - 1
return max(dfs(l - 1, j - 1), dfs(i - l, j)) + 1
- return dfs(n, k)
\ No newline at end of file
+ return dfs(n, k)
diff --git a/solution/1100-1199/1116.Print Zero Even Odd/Solution.py b/solution/1100-1199/1116.Print Zero Even Odd/Solution.py
index 2d931b714b..42c4bc7e06 100644
--- a/solution/1100-1199/1116.Print Zero Even Odd/Solution.py
+++ b/solution/1100-1199/1116.Print Zero Even Odd/Solution.py
@@ -1,13 +1,14 @@
from threading import Semaphore
+
class ZeroEvenOdd:
def __init__(self, n):
self.n = n
self.z = Semaphore(1)
self.e = Semaphore(0)
self.o = Semaphore(0)
-
- # printNumber(x) outputs "x", where x is an integer.
+
+ # printNumber(x) outputs "x", where x is an integer.
def zero(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(self.n):
self.z.acquire()
@@ -16,13 +17,13 @@ class ZeroEvenOdd:
self.o.release()
else:
self.e.release()
-
+
def even(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(2, self.n + 1, 2):
self.e.acquire()
printNumber(i)
self.z.release()
-
+
def odd(self, printNumber: 'Callable[[int], None]') -> None:
for i in range(1, self.n + 1, 2):
self.o.acquire()
diff --git a/solution/1400-1499/1419.Minimum Number of Frogs Croaking/Solution.py b/solution/1400-1499/1419.Minimum Number of Frogs Croaking/Solution.py
index 6ba76f9b10..54956e46b1 100644
--- a/solution/1400-1499/1419.Minimum Number of Frogs Croaking/Solution.py
+++ b/solution/1400-1499/1419.Minimum Number of Frogs Croaking/Solution.py
@@ -16,4 +16,4 @@ class Solution:
cnt[i - 1] -= 1
if i == 4:
x -= 1
- return -1 if x else ans
\ No newline at end of file
+ return -1 if x else ans
diff --git a/solution/2400-2499/2432.The Employee That Worked on the Longest Task/Solution.py b/solution/2400-2499/2432.The Employee That Worked on the Longest Task/Solution.py
index 6a1c92f04e..ac77c7d83d 100644
--- a/solution/2400-2499/2432.The Employee That Worked on the Longest Task/Solution.py
+++ b/solution/2400-2499/2432.The Employee That Worked on the Longest Task/Solution.py
@@ -6,4 +6,4 @@ class Solution:
if mx < t or (mx == t and ans > uid):
ans, mx = uid, t
last += t
- return ans
\ No newline at end of file
+ return ans
diff --git a/solution/CONTEST_README.md b/solution/CONTEST_README.md
index 63bb0083ea..7e716f42a9 100644
--- a/solution/CONTEST_README.md
+++ b/solution/CONTEST_README.md
@@ -8,18 +8,18 @@
如果竞赛积分处于段位的临界值,在每周比赛结束重新计算后会出现段位升级或降级的情况。段位升级或降级后会自动替换对应的荣誉勋章。
-| 段位 | 比例 | 段位名 | 国服分数线 | 勋章 |
-| ----- | ------ | -------- | --------- | --------------------------------------------------------------------------- |
-| LV3 | 5% | Guardian | ≥2251.88 |

|
-| LV2 | 20% | Knight | ≥1879.80 | 
|
-| LV1 | 75% | - | - | - |
+| 段位 | 比例 | 段位名 | 国服分数线 | 勋章 |
+| ---- | ---- | -------- | ----------- | ----------------------------------------------------------------------------------------------------------------------- |
+| LV3 | 5% | Guardian | ≥2251.88 | 
|
+| LV2 | 20% | Knight | ≥1879.80 | 
|
+| LV1 | 75% | - | - | - |
力扣竞赛 **全国排名前 10** 的用户,全站用户名展示为品牌橙色。
## 赛后估分网站
-- https://lcpredictor.herokuapp.com
-- https://lccn.lbao.site
+- https://lcpredictor.herokuapp.com
+- https://lccn.lbao.site
## 往期竞赛
diff --git a/solution/CONTEST_README_EN.md b/solution/CONTEST_README_EN.md
index 971d85c8cb..69a50f5dd2 100644
--- a/solution/CONTEST_README_EN.md
+++ b/solution/CONTEST_README_EN.md
@@ -11,11 +11,11 @@ If you are in the top 5% of the contest rating, you’ll get the “Guardian”
If you are in the top 25% of the contest rating, you’ll get the “Knight” badge.
-| Level | Proportion | Badge | Rating | |
-| ----- | ---------- | ---------- | -------------- | ----------------------------------------------------------------------------------------------------------------------- |
-| LV3 | 5\% | Guardian | ≥2228.90 | 
|
-| LV2 | 20\% | Knight | ≥1842.73 | 
|
-| LV1 | 75\% | - | - | - |
+| Level | Proportion | Badge | Rating | |
+| ----- | ---------- | -------- | ----------- | ----------------------------------------------------------------------------------------------------------------------- |
+| LV3 | 5\% | Guardian | ≥2228.90 | 
|
+| LV2 | 20\% | Knight | ≥1842.73 | 
|
+| LV1 | 75\% | - | - | - |
For top 10 users (excluding LCCN users), your LeetCode ID will be colored orange on the ranking board. You'll also have the honor with you when you post/comment under discuss.
diff --git a/solution/README.md b/solution/README.md
index 559fb5e5de..4380a31eb5 100644
--- a/solution/README.md
+++ b/solution/README.md
@@ -2687,4 +2687,4 @@
## 版权
-著作权归 [GitHub 开源社区 Doocs](https://github.com/doocs) 所有,商业转载请联系 [@yanglbme](mailto:contact@yanglibin.info) 获得授权,非商业转载请注明出处。
+著作权归 [GitHub 开源社区 Doocs](https://github.com/doocs) 所有,商业转载请联系 [@yanglbme](mailto:contact@yanglibin.info) 获得授权,非商业转载请注明出处。
\ No newline at end of file
diff --git a/solution/README_EN.md b/solution/README_EN.md
index cc1080d5e0..44f1019e1d 100644
--- a/solution/README_EN.md
+++ b/solution/README_EN.md
@@ -2685,4 +2685,4 @@ Press Control+F(or Command+F on the
## Copyright
-[@Doocs](https://github.com/doocs)
+[@Doocs](https://github.com/doocs)
\ No newline at end of file
diff --git a/solution/main.py b/solution/main.py
index 31b81c06bd..e53932d34c 100644
--- a/solution/main.py
+++ b/solution/main.py
@@ -1,3 +1,4 @@
+import json
import time
from datetime import timezone, timedelta, datetime
@@ -21,6 +22,8 @@ weekly_range = range(83, 500)
biweekly_range = range(1, 300)
WEEKLY_URL = 'https://leetcode.cn/contest/api/info/weekly-contest-{}/'
BIWEEKLY_URL = 'https://leetcode.cn/contest/api/info/biweekly-contest-{}/'
+WEEKLY_SLUG = 'weekly-contest-{}'
+BIWEEKLY_SLUG = 'biweekly-contest-{}'
class Spider:
@@ -57,18 +60,18 @@ class Spider:
form1 = {
'operationName': 'globalData',
'query': 'query globalData {\n feature {\n questionTranslation\n subscription\n signUp\n '
- 'discuss\n mockInterview\n contest\n store\n book\n chinaProblemDiscuss\n '
- 'socialProviders\n studentFooter\n cnJobs\n enableLsp\n enableWs\n '
- 'enableDebugger\n enableDebuggerAdmin\n enableDarkMode\n tasks\n '
- 'leetbook\n __typename\n }\n userStatus {\n isSignedIn\n isAdmin\n '
- 'isStaff\n isSuperuser\n isTranslator\n isPremium\n isVerified\n '
- 'isPhoneVerified\n isWechatVerified\n checkedInToday\n username\n '
- 'realName\n userSlug\n groups\n avatar\n optedIn\n '
- 'requestRegion\n region\n activeSessionId\n permissions\n notificationStatus {\n '
- 'lastModified\n numUnread\n __typename\n }\n completedFeatureGuides\n '
- 'useTranslation\n accountStatus {\n isFrozen\n inactiveAfter\n __typename\n '
- '}\n __typename\n }\n siteRegion\n chinaHost\n websocketUrl\n userBannedInfo {\n '
- 'bannedData {\n endAt\n bannedType\n __typename\n }\n __typename\n }\n}\n',
+ 'discuss\n mockInterview\n contest\n store\n book\n chinaProblemDiscuss\n '
+ 'socialProviders\n studentFooter\n cnJobs\n enableLsp\n enableWs\n '
+ 'enableDebugger\n enableDebuggerAdmin\n enableDarkMode\n tasks\n '
+ 'leetbook\n __typename\n }\n userStatus {\n isSignedIn\n isAdmin\n '
+ 'isStaff\n isSuperuser\n isTranslator\n isPremium\n isVerified\n '
+ 'isPhoneVerified\n isWechatVerified\n checkedInToday\n username\n '
+ 'realName\n userSlug\n groups\n avatar\n optedIn\n '
+ 'requestRegion\n region\n activeSessionId\n permissions\n notificationStatus {\n '
+ 'lastModified\n numUnread\n __typename\n }\n completedFeatureGuides\n '
+ 'useTranslation\n accountStatus {\n isFrozen\n inactiveAfter\n __typename\n '
+ '}\n __typename\n }\n siteRegion\n chinaHost\n websocketUrl\n userBannedInfo {\n '
+ 'bannedData {\n endAt\n bannedType\n __typename\n }\n __typename\n }\n}\n',
'variables': {},
}
headers = {
@@ -83,20 +86,20 @@ class Spider:
'operationName': 'questionData',
'variables': {'titleSlug': question_title_slug},
'query': 'query questionData($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n '
- 'questionId\n questionFrontendId\n categoryTitle\n boundTopicId\n title\n '
- 'titleSlug\n content\n translatedTitle\n translatedContent\n isPaidOnly\n '
- 'difficulty\n likes\n dislikes\n isLiked\n similarQuestions\n '
- 'contributors {\n username\n profileUrl\n avatarUrl\n __typename\n '
- '}\n langToValidPlayground\n topicTags {\n name\n slug\n '
- 'translatedName\n __typename\n }\n companyTagStats\n codeSnippets {\n '
- 'lang\n langSlug\n code\n __typename\n }\n stats\n hints\n '
- 'solution {\n id\n canSeeDetail\n __typename\n }\n status\n '
- 'sampleTestCase\n metaData\n judgerAvailable\n judgeType\n mysqlSchemas\n '
- 'enableRunCode\n envInfo\n book {\n id\n bookName\n pressName\n '
- 'source\n shortDescription\n fullDescription\n bookImgUrl\n '
- 'pressImgUrl\n productUrl\n __typename\n }\n isSubscribed\n '
- 'isDailyQuestion\n dailyRecordStatus\n editorType\n ugcQuestionId\n style\n '
- 'exampleTestcases\n __typename\n }\n}\n',
+ 'questionId\n questionFrontendId\n categoryTitle\n boundTopicId\n title\n '
+ 'titleSlug\n content\n translatedTitle\n translatedContent\n isPaidOnly\n '
+ 'difficulty\n likes\n dislikes\n isLiked\n similarQuestions\n '
+ 'contributors {\n username\n profileUrl\n avatarUrl\n __typename\n '
+ '}\n langToValidPlayground\n topicTags {\n name\n slug\n '
+ 'translatedName\n __typename\n }\n companyTagStats\n codeSnippets {\n '
+ 'lang\n langSlug\n code\n __typename\n }\n stats\n hints\n '
+ 'solution {\n id\n canSeeDetail\n __typename\n }\n status\n '
+ 'sampleTestCase\n metaData\n judgerAvailable\n judgeType\n mysqlSchemas\n '
+ 'enableRunCode\n envInfo\n book {\n id\n bookName\n pressName\n '
+ 'source\n shortDescription\n fullDescription\n bookImgUrl\n '
+ 'pressImgUrl\n productUrl\n __typename\n }\n isSubscribed\n '
+ 'isDailyQuestion\n dailyRecordStatus\n editorType\n ugcQuestionId\n style\n '
+ 'exampleTestcases\n __typename\n }\n}\n',
}
try:
@@ -120,7 +123,11 @@ class Spider:
except Exception as e:
print(e)
time.sleep(2)
- return self.get_question_detail(question_title_slug, retry - 1) if retry > 0 else {}
+ return (
+ self.get_question_detail(question_title_slug, retry - 1)
+ if retry > 0
+ else {}
+ )
@staticmethod
def format_question_detail(question_detail: dict) -> dict:
@@ -149,13 +156,18 @@ class Spider:
'url_en': url_en,
'relative_path_cn': path_cn,
'relative_path_en': path_en,
- 'title_cn': question_detail.get('translatedTitle') or question_title_en or '',
+ 'title_cn': question_detail.get('translatedTitle')
+ or question_title_en
+ or '',
'title_en': question_title_en or '',
'question_title_slug': question_title_slug,
'content_en': question_detail.get('content'),
- 'content_cn': question_detail.get('translatedContent') or question_detail.get('content') or '',
+ 'content_cn': question_detail.get('translatedContent')
+ or question_detail.get('content')
+ or '',
'tags_en': [e['name'] for e in topic_tags if e['name']] or [],
- 'tags_cn': [e['translatedName'] for e in topic_tags if e['translatedName']] or [],
+ 'tags_cn': [e['translatedName'] for e in topic_tags if e['translatedName']]
+ or [],
'difficulty_en': question_detail.get('difficulty'),
'difficulty_cn': difficulty.get(question_detail.get('difficulty')),
'code_snippets': question_detail.get('codeSnippets') or [],
@@ -187,10 +199,18 @@ class Contest:
def __init__(self, contest_seq: int, contest_type: int = 1):
double = contest_type % 2 == 0
url_pattern = BIWEEKLY_URL if double else WEEKLY_URL
+ slug_pattern = BIWEEKLY_SLUG if double else WEEKLY_SLUG
self.contest_type = contest_type
self.contest_url = url_pattern.format(contest_seq)
- self.contest_title = f'第 {contest_seq} 场双周赛' if double else f'第 {contest_seq} 场周赛'
- self.contest_title_en = f'Biweekly Contest {contest_seq}' if double else f'Weekly Contest {contest_seq}'
+ self.contest_title_slug = slug_pattern.format(contest_seq)
+ self.contest_title = (
+ f'第 {contest_seq} 场双周赛' if double else f'第 {contest_seq} 场周赛'
+ )
+ self.contest_title_en = (
+ f'Biweekly Contest {contest_seq}'
+ if double
+ else f'Weekly Contest {contest_seq}'
+ )
@staticmethod
def format_time(timestamp: int) -> str:
@@ -212,7 +232,7 @@ class Contest:
'contest_start_time': res['contest']['origin_start_time'],
'contest_duration': res['contest']['duration'],
'user_num': res['user_num'],
- 'question_slugs': question_slugs
+ 'question_slugs': question_slugs,
}
except Exception as e:
print(e)
@@ -229,27 +249,37 @@ class Contest:
duration = data['contest_duration']
cost_minutes = duration // 60
user_num = data['user_num']
- rows = [f'#### {title}({Contest.format_time(start_time)}, {cost_minutes} 分钟) 参赛人数 {user_num}\n']
+ rows = [
+ f'#### {title}({Contest.format_time(start_time)}, {cost_minutes} 分钟) 参赛人数 {user_num}\n'
+ ]
rows_en = [f'#### {title_en}\n']
for question in data['question_list']:
- frontend_question_id, title_cn, title_en, relative_path_cn, relative_path_en = question
+ (
+ frontend_question_id,
+ title_cn,
+ title_en,
+ relative_path_cn,
+ relative_path_en,
+ ) = question
rows.append(f'- [{frontend_question_id}. {title_cn}]({relative_path_cn})')
- rows_en.append(f'- [{frontend_question_id}. {title_en}]({relative_path_en})')
- return [
- start_time,
- '\n'.join(rows),
- '\n'.join(rows_en)
- ]
+ rows_en.append(
+ f'- [{frontend_question_id}. {title_en}]({relative_path_en})'
+ )
+ return [start_time, '\n'.join(rows), '\n'.join(rows_en)]
-def get_contests() -> List:
- res = []
+def get_contests(fetch_new=True) -> List:
+ res = [] if fetch_new else load_contest_result()
t = 0
+ d = {x.get('contest_title_slug'): x for x in res}
for r in (weekly_range, biweekly_range):
t += 1
cnt = 0
for i in r:
- contest_data = Contest(i, contest_type=t).get_data(retry=3)
+ c = Contest(i, contest_type=t)
+ if c.contest_title_slug in d:
+ continue
+ contest_data = c.get_data(retry=3)
if not contest_data:
cnt += 1
if cnt > 2:
@@ -257,6 +287,8 @@ def get_contests() -> List:
continue
print(contest_data)
res.append(contest_data)
+ d[c.contest_title_slug] = contest_data
+ save_contest_result(res)
return res
@@ -265,17 +297,28 @@ def get_contests() -> List:
cookie_cn, cookie_en = load_cookies()
spider = Spider(cookie_cn, cookie_en)
-# 题目详情列表
+# 是否刷新所有题目
+refresh_all = load_refresh_config()
+
question_details = {}
+if not refresh_all:
+ for item in load_result():
+ slug = item.get('question_title_slug')
+ if slug:
+ question_details[slug] = item
+
for q in spider.get_all_questions(retry=4):
slug = q['stat']['question__title_slug']
+ if slug in question_details:
+ print(f'{slug} 已存在, 跳过')
+ continue
detail = spider.get_question_detail(slug, retry=4)
time.sleep(0.3)
question_details[slug] = Spider.format_question_detail(detail)
# 周赛场次列表
-contest_list = get_contests()
+contest_list = get_contests(refresh_all)
cls = []
for contest in contest_list:
contest_title = contest['contest_title']
@@ -289,8 +332,13 @@ for contest in contest_list:
detail['md_table_row_en'][4] = contest_title_en
# 给周赛信息添加题目详情
- add = [detail['frontend_question_id'], detail['title_cn'],
- detail['title_en'], detail['relative_path_cn'], detail['relative_path_en']]
+ add = [
+ detail['frontend_question_id'],
+ detail['title_cn'],
+ detail['title_en'],
+ detail['relative_path_cn'],
+ detail['relative_path_en'],
+ ]
contest_question_list.append(add)
contest['question_list'] = contest_question_list
@@ -307,4 +355,5 @@ generate_summary(ls)
generate_contest_readme(cls)
# 刷新题目文件
-refresh(ls)
+if refresh_all:
+ refresh(ls)
diff --git a/solution/util.py b/solution/util.py
index 81093445cc..341b0094fc 100644
--- a/solution/util.py
+++ b/solution/util.py
@@ -29,10 +29,12 @@ contest_readme_en = load_template('contest_readme_template_en')
def load_cookies() -> Tuple[str, str]:
- cookie_cn, cookie_en = None, None
- with open("./.env", "r") as f:
+ cookie_cn, cookie_en = '', ''
+ env_file = './.env'
+ if not os.path.exists(env_file):
+ return cookie_cn, cookie_en
+ with open(env_file, "r") as f:
lines = f.readlines()
-
for line in lines:
if line.startswith("COOKIE_CN"):
parts = line.split("=")[1:]
@@ -46,17 +48,49 @@ def load_cookies() -> Tuple[str, str]:
return cookie_cn, cookie_en
+def load_refresh_config() -> bool:
+ env_file = './.env'
+ if not os.path.exists(env_file):
+ return False
+ with open(env_file, "r") as f:
+ lines = f.readlines()
+ for line in lines:
+ if line.startswith("REFRESH"):
+ parts = line.split("=")[1:]
+ return "=".join(parts).strip().strip('"') == 'True'
+ return False
+
+
def load_result() -> List[dict]:
- with open('./result.json', 'r', encoding='utf-8') as f:
+ result_file = './result.json'
+ if not os.path.exists(result_file):
+ return []
+ with open(result_file, 'r', encoding='utf-8') as f:
res = f.read()
return json.loads(res)
+def load_contest_result() -> List[dict]:
+ contest_result_file = './contest.json'
+ if not os.path.exists(contest_result_file):
+ return []
+ with open(contest_result_file, 'r', encoding='utf-8') as f:
+ res = f.read()
+ if res:
+ return json.loads(res)
+ return []
+
+
def save_result(data: List[dict]):
with open('./result.json', 'w', encoding='utf-8') as f:
f.write(json.dumps(data))
+def save_contest_result(data: List[dict]):
+ with open('./contest.json', 'w', encoding='utf-8') as f:
+ f.write(json.dumps(data))
+
+
def select_templates(category):
if category == 'Shell':
return [bash_readme_cn, bash_readme_en]
@@ -248,4 +282,4 @@ def generate_contest_readme(result: List):
f.write(content_cn)
content_en = contest_readme_en.format(content_en)
with open('./CONTEST_README_EN.md', 'w', encoding='utf-8') as f:
- f.write(content_en)
+ f.write(content_en)
\ No newline at end of file