Bear [source code]
import java.io.*;
public class Bear {
static final String HEADER = "# LeetCode Notes by QZhang JHU\n\nHere goes my journey of Leetcode\n\n" +
"Here is the synced [**Gitbook**](https://www.gitbook.com/book/vegito2002/leetcode-notes/details). E-book version download or online-reading is available.\n" +
"# Table of Problems\n";
static final String README =
"# My Leetcode Notes\n" +
"This book contains all notes from my LeetCode practice. They are produced by a script `Bear.java` which is also included in the `Bear` article in this book. Read for details. \n" +
"Briefly, each article corresponds to one question. Some question might have more than one article. This happens when the question has certain solutions that require separate compilation and debugging. \n" +
"Each article starts with a solution's code, usually my own first AC submission. Then there are notes. At the end of the article there is usually the problem description. \n" +
"Articles including `Printer`, `ListNode`, `TreeNode`, `Interval`, `Bear` etc. are all from utility class files. You do not need to read them. \n"
;
static final String SER_FILE = "../questions.ser";
static final String MEMO_FILE = "../qmemo.ser";
static final String TOPICS = " Dynamic Programming 106 String 102 Math 91 Hash Table 83 Tree 78 Depth-first Search 74 Binary Search 48 Two Pointers 42 Backtracking 37 Breadth-first Search 37 Stack 35 Design 33 Greedy 32 Bit Manipulation 31 Linked List 29 Heap 26 Sort 19 Graph 16 Divide and Conquer 14 Trie 14 Union Find 14 Binary Search Tree 13 Recursion 10 Segment Tree 8 Binary Indexed Tree 5 Queue 5 Topological Sort 5 Brainteaser 3 Minimax 3 Reservoir Sampling 2 Geometry 1 Memoization 1";
static final String COMPANIES = " Facebook 121 Microsoft 96 Amazon 91 Bloomberg 71 Uber 57 LinkedIn 52 Twitter 35 Airbnb 30 Apple 30 Snapchat 27 Yelp 21 Zenefits 21 Pocket Gems 15 Yahoo 15 Adobe 14 Baidu 9 Dropbox 9 Palantir 8 Coupang 7 IXL 7 Two Sigma 5 Akuna Capital 4 Alibaba 4 Hulu 4 Coursera 3 eBay 3 Intuit 3 LiveRamp 3 Pinterest 3 Square 3 Works Applications 3 Epic Systems 2 Expedia 2 GoDaddy 2 Houzz 2 Indeed 2 Lyft 2 Mathworks 2 NetEase 2 Tencent 2 Aetion 1 Affirm 1 AppDynamics 1 Citadel 1 Cloudera 1 databricks 1 DoorDash 1 Drawbridge 1 Fallible 1 ForUsAll 1 Garena 1 GE Digital 1 Gilt Groupe 1 Goldman Sachs 1 Helix 1 inmobi 1 Jingchi 1 Machine Zone 1 MAQ Software 1 Netsuite 1 Pony.ai 1 Poynt 1 Pure Storage 1 Quip 1 Quora 1 Rackspace 1 Radius 1 Riot Games 1 Roblox 1 Rubrik 1 Samsung 1 TripleByte 1 Valve 1 WAP 1 Wish 1 Yatra 1 Zappos 1";
Map<String, Integer> questions;
int unseen_seed = -1;
Map<String, Integer> qmemo;
Integer findMatch (Map<String, Integer> map, String _name) {
if (qmemo != null && qmemo.containsKey (_name))
return qmemo.get (_name);
String name = _name.toLowerCase ();
if (name.contains ("opt"))
name = name.substring (0, name.lastIndexOf ("opt"));
if (name.startsWith ("four"))
name = name.replace ("four", "4");
if (name.startsWith ("three"))
name = name.replace ("three", "3");
if (name.startsWith ("implementlru"))
name = name.replace ("implement", "");
int min_score = Integer.MAX_VALUE;
String res = "";
for (String s : map.keySet ()) {
int score = EditDistanceUtil.editDistance (s, name);
if (score < min_score) {
min_score = score;
res = s;
}
}
int num = min_score < 4 ? map.get (res) : (unseen_seed++);
if (num > 1782)
System.out.printf ("%s -> %s = %d, score:(%d)\n", _name, res, num, min_score);
qmemo.put (_name, num);
return num;
}
public Bear(String repo_readme, String outputName2) throws IOException{
questions = null;
try (ObjectInputStream ois = new ObjectInputStream (new FileInputStream (SER_FILE))) {
questions = (HashMap<String, Integer>) ois.readObject ();
} catch (Exception ex) {
System.out.printf ("%s not found\n", SER_FILE);
}
unseen_seed = questions.size () + 1000;
qmemo = null;
try (ObjectInputStream ois = new ObjectInputStream (new FileInputStream (MEMO_FILE))) {
qmemo = (HashMap<String, Integer>) ois.readObject ();
} catch (Exception ex) {
qmemo = new HashMap<> ();
}
File dir = new File(".");
File[] files = dir.listFiles((d, name) -> name.endsWith(".java") && !name.startsWith ("Contest"));
StringBuilder header = new StringBuilder(HEADER), gitbook_header = new StringBuilder (HEADER);
List<ProblemInfo> header_ls = new ArrayList<> (), gbheader_ls = new ArrayList<> ();
BufferedWriter writer;
for (int i = 0; i < files.length; i++) {
String fileName = files[i].getName();
String problemName = fileName.substring(0, fileName.indexOf("."));
if (problemName.matches ("Test[^0-9]*"))
continue;
ProblemInfo info = processFile(files[i], problemName);
System.out.print (".");
// TODO: does not categorize by companies/topics/difficulty for now;
int num = findMatch (questions, problemName);
header_ls.add(new ProblemInfo (num, info, String.format("%d. [LC%d %s](./articles/%s.md)%n", num, num, problemName, problemName)));
gbheader_ls.add(new ProblemInfo (num, info, String.format("%d. [LC%d %s](%s.md)%n", num, num, problemName, problemName)));
}
Collections.sort (header_ls, (a, b) -> a.num != b.num ? a.num - b.num : a.entry.length () - b.entry.length ());
Collections.sort (gbheader_ls, (a, b) -> a.num != b.num ? a.num - b.num : a.entry.length () - b.entry.length ());
// TODO append things to two SBs
for (int i = 0; i < header_ls.size (); i++) {
ProblemInfo pi1 = header_ls.get (i), pi2 = gbheader_ls.get (i);
header.append (pi1.entry);
gitbook_header.append (pi2.entry);
}
writer = new BufferedWriter(new FileWriter(repo_readme, false));
writer.write(header.toString());
writer.close();
writer = new BufferedWriter(new FileWriter("../articles/SUMMARY.md", false));
writer.write(gitbook_header.toString());
writer.close();
writer = new BufferedWriter(new FileWriter("../articles/README.md", false));
writer.write(README);
writer.close();
try (ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream (MEMO_FILE))) {
oos.writeObject (qmemo);
} catch (Exception ex) {
System.out.printf ("Error writing out memo file");
System.exit (1);
}
}
private ProblemInfo processFile(File file, String problemName) throws IOException{
Reader targetReader = new FileReader(file);
StringBuilder sb = new StringBuilder();
sb.append("## " + problemName + String.format (" [[source code]](../src/%s.java)\n", problemName) + "```java\n");
boolean code = true;
int block_count = 1;
String prev = "";
String difficulty = "NA", companies = "NA", topics = "NA";
try (BufferedReader br = new BufferedReader(targetReader)) {
String line = "";
while ((line = br.readLine()) != null) {
if (line.startsWith ("import java.util"))
continue;
line = line.replace("(https://discuss.leetcode.com/post/", "(https://discuss.leetcode.com/post/");
line = line.replace ("png?raw=1", "png?raw=1");
if (line.startsWith ("https://www.dropbox.com/s/") || line.startsWith ("> https://www.dropbox.com/s/")) {
Integer w = 400;
String[] tokens = line.split ("\\s+");
try {
w = Integer.parseInt (tokens[tokens.length - 1]);
} catch (Exception e) {}
line = line.startsWith (">") ? tokens[1] : tokens[0];
line = "<img src=\"" + line + "\" width=\"" + w + "\">";
}
if (!code) {
line = line.replace ("{{", "{% raw %} {{");
line = line.replace ("}}", "}} {% endraw %}");
}
if (line.equals("/*")) {
if (block_count == 1) {
code = false;
prev = line;
sb.append("```\n\n");
} else {
sb.append ("---\n### Problem Description\n");
}
block_count++;
} else if (line.equals("---") || line.equals ("===")) {
sb.append("\n" + "---" + "\n");
prev = line;
} else if (line.trim().startsWith ("```") || line.length () > 2 && line.substring (2).startsWith ("```")) {
String prefix = !code ? "\n" : "", suffix = code ? "\n" : "";
code = !code;
sb.append(prefix + line + "\n" + suffix);
prev = line;
}
else if (line.equals ("*/")) {
sb.append ("\n");
}
else if (block_count > 1) {
sb.append (line + " \n");
line = line.trim ().toLowerCase ();
if (line.startsWith ("difficulty")) {
difficulty = line.split (":")[1];
} else if (line.equals ("companies")) {
line = br.readLine ().trim ().toLowerCase ();
companies = line;
sb.append (line + " \n");
} else if (line.endsWith ("topics")) {
line = br.readLine ().trim ().toLowerCase ();
topics = line;
sb.append (line + " \n");
}
}
else {
sb.append(line + (code ? "" : " ") +"\n");
}
}
} catch (Exception e) {
e.printStackTrace();
}
// Mutation: write to file the re-processed content
String content = sb.toString();
String mdName = String.format("../articles/%s.md", problemName);
BufferedWriter bw = new BufferedWriter(new FileWriter(mdName, false));
bw.write(content);
bw.close();
return new ProblemInfo (difficulty, companies, topics);
}
static class ProblemInfo {
String difficulty, companies, topics, entry = "unitialized";
int num = 0;
ProblemInfo (String d, String c, String t) {difficulty = d; companies = c; topics = t; }
ProblemInfo (int num, ProblemInfo pi, String entry) {
this.num = num;
this.difficulty = pi.difficulty;
this.companies = pi.companies;
this.topics = pi.topics;
this.entry = entry;
}
}
public static void main(String[] args) {
try {
Bear combiner = new Bear("../README.md", "../Bear.md");
} catch (Exception e) {
e.printStackTrace();
}
}
}
A script to convert java source files into notes. All valid source files should consist of [code_block] [block_comment]+
The code_block is the content of the java file itself.
The first block_comment usually is the note content; The note content should be written in markdown format.
The second block_comment usually is the problem description.
This script takes advantage of this specified format and converts the java file into a readable markdown.
发现个奇葩的:
java> "[LC1 TwoSumIIIOPT]".compareTo ("[LC1 TwoSumIII]")
java.lang.Integer res4 = -14
java> "LC1 TwoSumIIIOPT".compareTo ("LC1 TwoSumIII")
java.lang.Integer res5 = 3
java> "\\[LC1 TwoSumIIIOPT\\]".compareTo ("\\[LC1 TwoSumIII\\]")
java.lang.Integer res6 = -13
这个是为什么啊? compareTo也自动识别regex?
escape之后还是不行;
Guoye给出了答案, 实际上这个compare和c的strcmp一样, 就是一个一个的比, 不会考虑长度, 所以第一个之所以认为左边小, 是因为:
java> "O".compareTo ("]")
java.lang.Integer res0 = -14
不要想当然的认为他会帮你考虑长度;