This repository has been archived by the owner on Sep 20, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 165
/
Copy pathbuildProblemDir.go
217 lines (164 loc) · 4.4 KB
/
buildProblemDir.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
package main
import (
"fmt"
"log"
"os"
"runtime/debug"
"strings"
"syscall"
"github.com/aQuaYi/GoKit"
)
func buildProblemDir(problemNum int) {
log.Printf("~~ 开始生成第 %d 题的文件夹 ~~\n", problemNum)
// 获取 LeetCode 的记录文件
lc := newLeetCode()
// 检查 problemNum 的合法性
if problemNum >= len(lc.Problems) {
log.Panicf("%d 超出题目范围,请核查题号。", problemNum)
}
if lc.Problems[problemNum].ID == 0 {
log.Panicf("%d 号题不存,请核查题号。", problemNum)
}
if lc.Problems[problemNum].IsPaid {
log.Panicf("%d 号题需要付费。如果已经订阅,请注释掉本代码。", problemNum)
}
if lc.Problems[problemNum].HasNoGoOption {
log.Panicf("%d 号题,没有提供 Go 解答选项。请核查后,修改 unavailable.json 中的记录。", problemNum)
}
// 需要创建答题文件夹
build(lc.Problems[problemNum])
log.Printf("~~ 第 %d 题的文件夹,已经生成 ~~\n", problemNum)
}
func build(p problem) {
if GoKit.Exist(p.Dir()) {
log.Panicf("第 %d 题的文件夹已经存在,请 **移除** %s 文件夹后,再尝试。", p.ID, p.Dir())
}
defer func() {
if err := recover(); err != nil {
debug.PrintStack()
log.Println(err)
log.Println("清理不必要的文件")
os.RemoveAll(p.Dir())
}
}()
// windows用户注释这两行
mask := syscall.Umask(0)
defer syscall.Umask(mask)
// 创建目录
err := os.Mkdir(p.Dir(), 0755)
if err != nil {
log.Panicf("无法创建目录,%s :%s", p.Dir(), err)
}
log.Printf("开始创建 %d %s 的文件夹...\n", p.ID, p.Title)
content, fc := getGraphql(p)
if fc == "" {
log.Panicf("查无Go语言写法")
}
// 利用 chrome 打开题目页面
// go func() {
// cmd := exec.Command("google-chrome", p.link())
// _, err = cmd.Output()
// if err != nil {
// panic(err.Error())
// }
// }()
// fc := getFunction(p.link())
fcName, para, ans, _ := parseFunction(fc)
creatGo(p, fc, ans)
creatGoTest(p, fcName, para, ans)
creatREADME(p, content)
log.Printf("%d.%s 的文件夹,创建完毕。\n", p.ID, p.Title)
}
var typeMap = map[string]string{
"int": "0",
"float64": "0",
"string": "\"\"",
"bool": "false",
}
func creatGo(p problem, function, ansType string) {
fileFormat := `package %s
%s
%s
`
treeNodeDefine := ""
if strings.Contains(function, "*TreeNode") {
treeNodeDefine = `
import "github.com/aQuaYi/LeetCode-in-Go/kit"
// TreeNode is pre-defined...
// type TreeNode struct {
// Val int
// Left *TreeNode
// Right *TreeNode
// }
type TreeNode = kit.TreeNode
`
}
content := fmt.Sprintf(fileFormat, p.packageName(), treeNodeDefine, function)
if v, ok := typeMap[ansType]; ok {
content = strings.Replace(content, "nil", v, 1)
}
filename := fmt.Sprintf("%s/%s.go", p.Dir(), p.TitleSlug)
write(filename, content)
vscodeOpen(filename)
}
func creatGoTest(p problem, fcName, para, ansType string) {
testCasesFormat := `var tcs = []struct {
%s
ans %s
}{
// 可以有多个 testcase
}`
para = strings.Replace(para, ",", "\n", -1)
testCases := fmt.Sprintf(testCasesFormat, para, ansType)
testFuncFormat := `
func Test_%s(t *testing.T) {
a := assert.New(t)
for _, tc := range tcs {
a.Equal(tc.ans, %s(%s), "输入:%s", tc)
}
}`
tcPara := getTcPara(para)
testFunc := fmt.Sprintf(testFuncFormat, fcName, fcName, tcPara, `%v`)
benchFuncFormat := `
func Benchmark_%s(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, tc := range tcs {
%s(%s)
}
}
}`
benchFunc := fmt.Sprintf(benchFuncFormat, fcName, fcName, tcPara)
fileFormat := `package %s
import (
"testing"
"github.com/stretchr/testify/assert"
)
// tcs is testcase slice
%s
%s
%s
`
content := fmt.Sprintf(fileFormat, p.packageName(), testCases, testFunc, benchFunc)
filename := fmt.Sprintf("%s/%s_test.go", p.Dir(), p.TitleSlug)
write(filename, content)
vscodeOpen(filename)
}
// 把 函数的参数 变成 tc 的参数
func getTcPara(para string) string {
// 把 para 按行切分
paras := strings.Split(para, "\n")
// 把单个参数按空格,切分成参数名和参数类型
temp := make([][]string, len(paras))
for i := range paras {
temp[i] = strings.Split(strings.TrimSpace(paras[i]), ` `)
}
// 在参数名称前添加 "tc." 并组合在一起
res := ""
for i := 0; i < len(temp); i++ {
res += ", tc." + temp[i][0]
}
return res[2:]
}
func (p problem) packageName() string {
return fmt.Sprintf("problem%04d", p.ID)
}