/
helper.go
194 lines (177 loc) · 5.21 KB
/
helper.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
package leetcode
import (
"bytes"
"path/filepath"
"strings"
"unicode"
)
// 细分的话有四种题目类型:
// 函数-无预定义类型,绝大多数题目都是这个类型
// 函数-有预定义类型,如 LC174C
// 方法-无预定义类型,如 LC175C
// 方法-有预定义类型,如 LC163B
func parseCode(code string) (funcName string, isFuncProblem bool, funcLos []int) {
lines := strings.Split(code, "\n")
if strings.Contains(code, "func Constructor(") {
// 编写方法
for lo, line := range lines {
if strings.HasPrefix(line, "func Constructor(") { // 构造器定义
funcLos = append(funcLos, lo)
} else if strings.HasPrefix(line, "func (") { // 方法定义
funcLos = append(funcLos, lo)
}
}
funcName = "Constructor"
} else {
// 编写函数
for lo, line := range lines {
if strings.HasPrefix(line, "func ") { // 函数定义
i := strings.IndexByte(line, '(')
return strings.TrimSpace(line[5:i]), true, []int{lo}
}
}
}
return
}
//
type modifyLineFunc func(funcDefineLine string) string
func _toLower(c byte) byte {
if 'A' <= c && c <= 'Z' {
return c - 'A' + 'a'
}
return c
}
func toGolangReceiverName(funcDefineLine string) string {
if !strings.HasPrefix(funcDefineLine, "func (this *") {
return funcDefineLine
}
// 由于采用的是全局变量的写法,receiver 可以去掉
return strings.Replace(funcDefineLine, "this *", "", 1)
}
func lowerArgsFirstChar(funcDefineLine string) string {
code := []byte(funcDefineLine)
i := bytes.LastIndexByte(code, '(')
code[i+1] = _toLower(code[i+1])
for ; i < len(code); i++ {
if code[i] == ',' {
code[i+2] = _toLower(code[i+2])
}
}
return string(code)
}
var inputNameReplacer *strings.Replacer
func init() {
// 替换常见变量名(数组、字符串等)
oldNew := []string{
// 数组、矩阵
"nums", "a",
"nums1", "x",
"nums2", "y",
"nums3", "z",
"arr", "a",
"array", "a",
"scores", "a",
"values", "a",
"vals", "a",
"stones", "a",
"cards", "a",
"prices", "a",
"grades", "a",
"beans", "a",
"mat", "a",
"matrix", "a",
"grid", "g",
"grid1", "g1",
"grid2", "g2",
"words", "a",
// 字符串
"word", "s",
"word1", "x",
"word2", "y",
"s1", "x",
"s2", "y",
// 其余常见变量名
"num", "n",
"num1", "x",
"num2", "y",
"num3", "z",
"size", "n",
"edges", "es",
"points", "ps",
"pairs", "ps",
"queries", "qs",
"startPos", "st",
"start", "st",
"source", "st",
"target", "trg",
"total", "tot",
"limit", "lim",
"index", "id",
"index1", "id1",
"index2", "id2",
"dist", "dis",
"timestamp", "ts",
"diff", "d",
}
for i := range oldNew {
oldNew[i] += " " // 由于要匹配变量名+空格+类型,为了防止修改到意外的位置,通过加一个空格来简单地实现匹配
}
inputNameReplacer = strings.NewReplacer(oldNew...)
inputNameReplacer.Replace("") // 触发内部的 buildOnce
}
func renameInputArgs(funcDefineLine string) string {
return inputNameReplacer.Replace(funcDefineLine)
}
func _parseReturnType(line string) string {
i := strings.LastIndexByte(line, ')')
return strings.TrimSpace(line[i+1 : len(line)-2])
}
func namedReturnFunc(name string) modifyLineFunc {
return func(funcDefineLine string) string {
returnType := _parseReturnType(funcDefineLine)
if returnType == "" {
return funcDefineLine
} // 无返回值
if returnType == "int64" {
return funcDefineLine
}
returnName := name
if strings.HasPrefix(funcDefineLine, "func Constructor(") {
returnName = "_"
}
i := strings.LastIndexByte(funcDefineLine, ')') + 2
return funcDefineLine[:i] + "(" + returnName + " " + returnType + ") {"
}
}
func modifyDefaultCode(code string, funcLos []int, funcList []modifyLineFunc, customFuncContent string) string {
sep := "\n"
if strings.ContainsRune(code, '\r') {
sep = "\r\n"
}
lines := strings.Split(code, sep)
for _, lo := range funcLos {
if tp := _parseReturnType(lines[lo]); tp != "" {
if tp == "int64" {
customFuncContent = "\tans := 0\n" + customFuncContent /* return */ + " int64(ans)"
}
lines[lo+1] = customFuncContent
}
for _, f := range funcList {
lines[lo] = f(lines[lo])
}
}
return strings.Join(lines, sep)
}
func findNonASCII(s string) int {
// this is faster than `for _, c := range s`, because there is no rune conversion
for i := range s {
if s[i] > unicode.MaxASCII {
return i
}
}
return -1
}
func absPath(path string) string {
p, _ := filepath.Abs(path)
return p
}