add (4979B)
1#!/usr/bin/env python3 2 3from inscriptis import annotation 4import inscriptis, re, requests, sys 5from bs4 import BeautifulSoup 6from glob import glob 7 8name = sys.argv[1] or sys.exit(1) 9 10def reorder(text, width): 11 chunks = text.split("\n\n") 12 out = [] 13 for i,c in enumerate(chunks): 14 if (":" in c or "* " in c) and "Follow-up" not in c: 15 for l in c.split("\n"): 16 prefix = len(l) - len(l.replace("-", " ").lstrip()) 17 indent = l[:prefix] 18 if i > 0 and chunks[i-1].startswith("*Example "): 19 indent = " " + indent 20 l2 = [] 21 for w in l[prefix:].split(" "): 22 if len(" ".join(l2 + [w])) > width: 23 out.append(indent + " ".join(l2)) 24 indent = indent.replace("-", " ") 25 l2 = [] 26 l2.append(w) 27 if l == "" or l2 != []: 28 out.append(indent + " ".join(l2)) 29 out.append("") 30 continue 31 words = re.split(" |\n|\t", c) 32 line = "" 33 for w in words: 34 if w == "": 35 continue 36 if len(line) + len(w) + 1 > width: 37 out.append(line) 38 while len(w) > width: 39 out.append(w[:width]) 40 w = w[80:] 41 line = "" 42 line += "" if line == "" else " " 43 line += w; 44 if i == len(chunks) - 1: 45 out.append(line) 46 else: 47 out.append(line) 48 out.append("") 49 return out 50 51json_data = { 52 'query': '\n query questionContent($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n content\n mysqlSchemas\n dataSchemas\n }\n}\n ', 53 'variables': { 54 'titleSlug': name, 55 }, 56 'operationName': 'questionContent', 57} 58r = requests.post('https://leetcode.com/graphql/', json=json_data) 59description_html = r.json()["data"]["question"]["content"] 60description_info = inscriptis.get_annotated_text(description_html, 61 inscriptis.ParserConfig(annotation_rules = {"strong": ["emphasis"]})) 62emphasis = sorted(description_info["label"], key=lambda v: v[0]) 63description = description_info["text"] 64offset = 0 65for start,end,_ in emphasis: 66 inner = description[start+offset:end+offset] 67 left = len(inner) - len(inner.lstrip()) 68 description = description[:start+offset+left] \ 69 + "*" + inner[left:] \ 70 + "*" + description[end+offset:] 71 offset += 2 72lines = description.split("\n") 73plen = min([len(l) - len(l.lstrip()) for l in lines if l.strip() != ""]) 74lines = [l[plen:].rstrip() for l in lines] 75lines = re.sub("\n\n+", "\n\n", "\n".join(lines)).split("\n") 76lines = reorder("\n".join(lines), 76) 77#lines = "\n".join(lines).strip().split("\n") 78description_comment = "\n".join(["/// " + l if l != "" else "///" for l in lines]) 79 80json_data = { 81 'query': '\n query questionTitle($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n title\n titleSlug\n isPaidOnly\n difficulty\n likes\n dislikes\n categoryTitle\n }\n}\n ', 82 'variables': { 83 'titleSlug': name, 84 }, 85 'operationName': 'questionTitle', 86} 87r = requests.post('https://leetcode.com/graphql/', json=json_data) 88num = int(r.json()["data"]["question"]["questionFrontendId"]) 89title = r.json()["data"]["question"]["title"] 90difficulty = r.json()["data"]["question"]["difficulty"] 91info_comment = f"/// {num}. {title} ({difficulty})\n///" 92header_comment = info_comment + "\n" + description_comment 93 94json_data = { 95 'query': '\n query questionEditorData($titleSlug: String!) {\n question(titleSlug: $titleSlug) {\n questionId\n questionFrontendId\n codeSnippets {\n lang\n langSlug\n code\n }\n envInfo\n enableRunCode\n hasFrontendPreview\n frontendPreviews\n }\n}\n ', 96 'variables': { 97 'titleSlug': name, 98 }, 99 'operationName': 'questionEditorData', 100} 101r = requests.post('https://leetcode.com/graphql/', json=json_data) 102solution_impl = next(c for c in r.json()["data"]["question"]["codeSnippets"] if c["lang"] == "Rust")["code"] 103 104main_footer = """ 105#[cfg(test)] 106mod tests { 107 use crate::Solution; 108 109 #[test] 110 fn test() { 111 } 112} 113""" 114with open(f"src/bin/{num:04}-{name}.rs", "w+") as f: 115 f.write(header_comment + "\n\n") 116 f.write("use leetcode::*;\n\n") 117 f.write("struct Solution {}\n\n") 118 f.write(solution_impl + "\n\n") 119 f.write("pub fn main() {\n}\n") 120 f.write(main_footer) 121 122cargo_header = """[package] 123name = "leetcode" 124version = "0.1.0" 125edition = "2021" 126""" 127with open("Cargo.toml", "w+") as f: 128 f.write(cargo_header) 129 f.write("\n") 130 for path in glob("src/bin/*.rs"): 131 num = int(path.rsplit("/",1)[1].split("-",1)[0]) 132 f.write("[[bin]]\n") 133 f.write(f"name = \"{num}\"\n") 134 f.write(f"path = \"{path}\"\n") 135 f.write("\n")