Skip to content

Commit c83589b

Browse files
committed
feat:优化指令的交互性&修复部分题目无法正常生成测试样例的问题
1 parent 7d539c6 commit c83589b

File tree

10 files changed

+171
-73
lines changed

10 files changed

+171
-73
lines changed

Readme.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
- [x] 2.模板:从detail中获取输入用例的数据填充@Testcase
1010
- [x] 3.模板:获取跳转每日一题的链接替换@url
1111
- [x] 4.函数:优化时间和资源统计函数
12-
- [ ] 5.优化创建时的体验,添加重复时候的确认覆盖或者添加额外符号
12+
- [x] 5.优化创建时的体验,添加重复时候的确认覆盖或者添加额外符号
1313
- [ ] 6.特殊数据结构的处理(ListNode,Stack等)的处理
14-
- [ ] 7.创建某一特定编号的题目脚本,以及实现随机题目【随机题目汇集本地题目,然后排除自己本地存在的题目进行随机】
15-
- [ ] 8.实现在编辑器中预览图片
14+
- [x] 7.创建某一特定编号的题目脚本,以及实现随机题目【随机题目汇集本地题目,然后排除自己本地存在的题目进行随机】
15+
- [ ] 8.实现在编辑器中预览图片(感觉可以不做)
1616

1717
## How to use for yourself ?
1818

common/resources/store.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"today":"2182","today-question-info":{"id":"2809","enName":"minimum-time-to-make-array-sum-at-most-x","title":"使数组和小于等于 x 的最少时间","detail":"<p>给你两个长度相等下标从 <strong>0</strong>&nbsp;开始的整数数组&nbsp;<code>nums1</code> 和&nbsp;<code>nums2</code>&nbsp;。每一秒,对于所有下标&nbsp;<code>0 &lt;= i &lt; nums1.length</code>&nbsp;,<code>nums1[i]</code>&nbsp;的值都增加&nbsp;<code>nums2[i]</code>&nbsp;。操作&nbsp;<strong>完成后</strong>&nbsp;,你可以进行如下操作:</p>\n\n<ul>\n\t<li>选择任一满足&nbsp;<code>0 &lt;= i &lt; nums1.length</code>&nbsp;的下标 <code>i</code>&nbsp;,并使&nbsp;<code>nums1[i] = 0</code>&nbsp;。</li>\n</ul>\n\n<p>同时给你一个整数&nbsp;<code>x</code>&nbsp;。</p>\n\n<p>请你返回使&nbsp;<code>nums1</code>&nbsp;中所有元素之和 <strong>小于等于</strong>&nbsp;<code>x</code>&nbsp;所需要的 <strong>最少</strong>&nbsp;时间,如果无法实现,那么返回 <code>-1</code>&nbsp;。</p>\n\n<p>&nbsp;</p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<b>输入:</b>nums1 = [1,2,3], nums2 = [1,2,3], x = 4\n<b>输出:</b>3\n<b>解释:</b>\n第 1 秒,我们对 i = 0 进行操作,得到 nums1 = [0,2+2,3+3] = [0,4,6] 。\n第 2 秒,我们对 i = 1 进行操作,得到 nums1 = [0+1,0,6+3] = [1,0,9] 。\n第 3 秒,我们对 i = 2 进行操作,得到 nums1 = [1+1,0+2,0] = [2,2,0] 。\n现在 nums1 的和为 4 。不存在更少次数的操作,所以我们返回 3 。\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<b>输入:</b>nums1 = [1,2,3], nums2 = [3,3,3], x = 4\n<b>输出:</b>-1\n<b>解释:</b>不管如何操作,nums1 的和总是会超过 x 。\n</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 &lt;= nums1.length &lt;= 10<sup>3</sup></code></li>\n\t<li><code>1 &lt;= nums1[i] &lt;= 10<sup>3</sup></code></li>\n\t<li><code>0 &lt;= nums2[i] &lt;= 10<sup>3</sup></code></li>\n\t<li><code>nums1.length == nums2.length</code></li>\n\t<li><code>0 &lt;= x &lt;= 10<sup>6</sup></code></li>\n</ul>\n","jsCode":"/**\n * @param {number[]} nums1\n * @param {number[]} nums2\n * @param {number} x\n * @return {number}\n */\nvar minimumTime = function(nums1, nums2, x) {\n\n};","date":"2024-01-19"},"today-tag":"82","random-id":1314,"random-question-info":{"enName":"regular-expression-matching","title":"正则表达式匹配","detail":"<p>给你一个字符串&nbsp;<code>s</code>&nbsp;和一个字符规律&nbsp;<code>p</code>,请你来实现一个支持 <code>'.'</code>&nbsp;和&nbsp;<code>'*'</code>&nbsp;的正则表达式匹配。</p>\n\n<ul>\n\t<li><code>'.'</code> 匹配任意单个字符</li>\n\t<li><code>'*'</code> 匹配零个或多个前面的那一个元素</li>\n</ul>\n\n<p>所谓匹配,是要涵盖&nbsp;<strong>整个&nbsp;</strong>字符串&nbsp;<code>s</code>的,而不是部分字符串。</p>\n&nbsp;\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong>s = \"aa\", p = \"a\"\n<strong>输出:</strong>false\n<strong>解释:</strong>\"a\" 无法匹配 \"aa\" 整个字符串。\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>s = \"aa\", p = \"a*\"\n<strong>输出:</strong>true\n<strong>解释:</strong>因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 \"aa\" 可被视为 'a' 重复了一次。\n</pre>\n\n<p><strong>示例&nbsp;3:</strong></p>\n\n<pre>\n<strong>输入:</strong>s = \"ab\", p = \".*\"\n<strong>输出:</strong>true\n<strong>解释:</strong>\".*\" 表示可匹配零个或多个('*')任意字符('.')。\n</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 &lt;= s.length&nbsp;&lt;= 20</code></li>\n\t<li><code>1 &lt;= p.length&nbsp;&lt;= 20</code></li>\n\t<li><code>s</code>&nbsp;只包含从&nbsp;<code>a-z</code>&nbsp;的小写字母。</li>\n\t<li><code>p</code>&nbsp;只包含从&nbsp;<code>a-z</code>&nbsp;的小写字母,以及字符&nbsp;<code>.</code>&nbsp;和&nbsp;<code>*</code>。</li>\n\t<li>保证每次出现字符&nbsp;<code>*</code> 时,前面都匹配到有效的字符</li>\n</ul>\n","id":"10","jsCode":"/**\n * @param {string} s\n * @param {string} p\n * @return {boolean}\n */\nvar isMatch = function(s, p) {\n\n};"},"specified-question-info":{"enName":"matrix-block-sum","title":"矩阵区域和","detail":"<p>给你一个 <code>m x n</code> 的矩阵 <code>mat</code> 和一个整数 <code>k</code> ,请你返回一个矩阵 <code>answer</code> ,其中每个 <code>answer[i][j]</code> 是所有满足下述条件的元素 <code>mat[r][c]</code> 的和: </p>\n\n<ul>\n\t<li><code>i - k <= r <= i + k, </code></li>\n\t<li><code>j - k <= c <= j + k</code> 且</li>\n\t<li><code>(r, c)</code> 在矩阵内。</li>\n</ul>\n\n<p> </p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong>mat = [[1,2,3],[4,5,6],[7,8,9]], k = 1\n<strong>输出:</strong>[[12,21,16],[27,45,33],[24,39,28]]\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>mat = [[1,2,3],[4,5,6],[7,8,9]], k = 2\n<strong>输出:</strong>[[45,45,45],[45,45,45],[45,45,45]]\n</pre>\n\n<p> </p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>m == mat.length</code></li>\n\t<li><code>n == mat[i].length</code></li>\n\t<li><code>1 <= m, n, k <= 100</code></li>\n\t<li><code>1 <= mat[i][j] <= 100</code></li>\n</ul>\n","id":"1314","jsCode":"/**\n * @param {number[][]} mat\n * @param {number} k\n * @return {number[][]}\n */\nvar matrixBlockSum = function(mat, k) {\n\n};"}}
1+
{"today":"2182","today-question-info":{"enName":"split-strings-by-separator","title":"按分隔符拆分字符串","detail":"<p>给你一个字符串数组 <code>words</code> 和一个字符 <code>separator</code> ,请你按 <code>separator</code> 拆分 <code>words</code> 中的每个字符串。</p>\n\n<p>返回一个由拆分后的新字符串组成的字符串数组,<strong>不包括空字符串</strong> 。</p>\n\n<p><strong>注意</strong></p>\n\n<ul>\n\t<li><code>separator</code> 用于决定拆分发生的位置,但它不包含在结果字符串中。</li>\n\t<li>拆分可能形成两个以上的字符串。</li>\n\t<li>结果字符串必须保持初始相同的先后顺序。</li>\n</ul>\n\n<p>&nbsp;</p>\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong>words = [\"one.two.three\",\"four.five\",\"six\"], separator = \".\"\n<strong>输出:</strong>[\"one\",\"two\",\"three\",\"four\",\"five\",\"six\"]\n<strong>解释:</strong>在本示例中,我们进行下述拆分:\n\n\"one.two.three\" 拆分为 \"one\", \"two\", \"three\"\n\"four.five\" 拆分为 \"four\", \"five\"\n\"six\" 拆分为 \"six\" \n\n因此,结果数组为 [\"one\",\"two\",\"three\",\"four\",\"five\",\"six\"] 。</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>words = [\"$easy$\",\"$problem$\"], separator = \"$\"\n<strong>输出:</strong>[\"easy\",\"problem\"]\n<strong>解释:</strong>在本示例中,我们进行下述拆分:\n\n\"$easy$\" 拆分为 \"easy\"(不包括空字符串)\n\"$problem$\" 拆分为 \"problem\"(不包括空字符串)\n\n因此,结果数组为 [\"easy\",\"problem\"] 。\n</pre>\n\n<p><strong>示例 3:</strong></p>\n\n<pre>\n<strong>输入:</strong>words = [\"|||\"], separator = \"|\"\n<strong>输出:</strong>[]\n<strong>解释:</strong>在本示例中,\"|||\" 的拆分结果将只包含一些空字符串,所以我们返回一个空数组 [] 。 </pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 &lt;= words.length &lt;= 100</code></li>\n\t<li><code>1 &lt;= words[i].length &lt;= 20</code></li>\n\t<li><code>words[i]</code> 中的字符要么是小写英文字母,要么就是字符串 <code>\".,|$#@\"</code> 中的字符(不包括引号)</li>\n\t<li><code>separator</code> 是字符串 <code>\".,|$#@\"</code> 中的某个字符(不包括引号)</li>\n</ul>\n","id":"2788","jsCode":"/**\n * @param {string[]} words\n * @param {character} separator\n * @return {string[]}\n */\nvar splitWordsBySeparator = function(words, separator) {\n\n};","date":"2024-01-20"},"today-tag":"82","random-id":1314,"random-question-info":{"enName":"regular-expression-matching","title":"正则表达式匹配","detail":"<p>给你一个字符串&nbsp;<code>s</code>&nbsp;和一个字符规律&nbsp;<code>p</code>,请你来实现一个支持 <code>'.'</code>&nbsp;和&nbsp;<code>'*'</code>&nbsp;的正则表达式匹配。</p>\n\n<ul>\n\t<li><code>'.'</code> 匹配任意单个字符</li>\n\t<li><code>'*'</code> 匹配零个或多个前面的那一个元素</li>\n</ul>\n\n<p>所谓匹配,是要涵盖&nbsp;<strong>整个&nbsp;</strong>字符串&nbsp;<code>s</code>的,而不是部分字符串。</p>\n&nbsp;\n\n<p><strong>示例 1:</strong></p>\n\n<pre>\n<strong>输入:</strong>s = \"aa\", p = \"a\"\n<strong>输出:</strong>false\n<strong>解释:</strong>\"a\" 无法匹配 \"aa\" 整个字符串。\n</pre>\n\n<p><strong>示例 2:</strong></p>\n\n<pre>\n<strong>输入:</strong>s = \"aa\", p = \"a*\"\n<strong>输出:</strong>true\n<strong>解释:</strong>因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 \"aa\" 可被视为 'a' 重复了一次。\n</pre>\n\n<p><strong>示例&nbsp;3:</strong></p>\n\n<pre>\n<strong>输入:</strong>s = \"ab\", p = \".*\"\n<strong>输出:</strong>true\n<strong>解释:</strong>\".*\" 表示可匹配零个或多个('*')任意字符('.')。\n</pre>\n\n<p>&nbsp;</p>\n\n<p><strong>提示:</strong></p>\n\n<ul>\n\t<li><code>1 &lt;= s.length&nbsp;&lt;= 20</code></li>\n\t<li><code>1 &lt;= p.length&nbsp;&lt;= 20</code></li>\n\t<li><code>s</code>&nbsp;只包含从&nbsp;<code>a-z</code>&nbsp;的小写字母。</li>\n\t<li><code>p</code>&nbsp;只包含从&nbsp;<code>a-z</code>&nbsp;的小写字母,以及字符&nbsp;<code>.</code>&nbsp;和&nbsp;<code>*</code>。</li>\n\t<li>保证每次出现字符&nbsp;<code>*</code> 时,前面都匹配到有效的字符</li>\n</ul>\n","id":"10","jsCode":"/**\n * @param {string} s\n * @param {string} p\n * @return {boolean}\n */\nvar isMatch = function(s, p) {\n\n};"},"specified-question-info":{"enName":"SNJvJP","title":"乐团站位","detail":"某乐团的演出场地可视作 `num * num` 的二维矩阵 `grid`(左上角坐标为 `[0,0]`),每个位置站有一位成员。乐团共有 `9` 种乐器,乐器编号为 `1~9`,每位成员持有 `1` 个乐器。\n\n为保证声乐混合效果,成员站位规则为:自 `grid` 左上角开始顺时针螺旋形向内循环以 `1,2,...,9` 循环重复排列。例如当 num = `5` 时,站位如图所示\n\n![image.png](https://pic.leetcode-cn.com/1616125411-WOblWH-image.png)\n\n\n请返回位于场地坐标 [`Xpos`,`Ypos`] 的成员所持乐器编号。\n\n**示例 1:**\n>输入:`num = 3, Xpos = 0, Ypos = 2`\n>\n>输出:`3`\n>\n>解释:\n![image.png](https://pic.leetcode-cn.com/1616125437-WUOwsu-image.png)\n\n\n**示例 2:**\n>输入:`num = 4, Xpos = 1, Ypos = 2`\n>\n>输出:`5`\n>\n>解释:\n![image.png](https://pic.leetcode-cn.com/1616125453-IIDpxg-image.png)\n\n\n**提示:**\n- `1 <= num <= 10^9`\n- `0 <= Xpos, Ypos < num`","id":"LCP 29","jsCode":"/**\n * @param {number} num\n * @param {number} xPos\n * @param {number} yPos\n * @return {number}\n */\nvar orchestraLayout = function(num, xPos, yPos) {\n\n};"}}

common/utils/createQuestion.js

+41-17
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,52 @@
11
const fs = require("fs");
22
const path = require("path");
3-
3+
const readlinePromises = require('node:readline/promises');
4+
const {getCountBySameName} = require("./getCountBySameName");
5+
const rl = readlinePromises.createInterface({
6+
input: process.stdin,
7+
output: process.stdout,
8+
});
49
function createQuestion(newPath) {
510
return new Promise((resolve, reject) => {
6-
const newDir = path.normalize(`./src/${newPath}`);
711
const sourceFilePath = path.normalize("./common/template/template.js")
8-
const newFilePath = path.join(newDir, "index.js")
12+
let newDir = path.normalize(`./src/${newPath}`);
13+
let newFilePath = path.join(newDir, "index.js")
914
// 判断是否存在
10-
fs.exists(newFilePath, (exists) => {
15+
fs.exists(newFilePath, async (exists) => {
1116
if (exists) {
12-
reject(`./src/${newPath} 已存在,请检查目录!`);
13-
} else {
14-
try {
15-
16-
// 创建目录
17-
fs.mkdir(newDir, { recursive: true }, () => {
18-
// 复制文件
19-
fs.copyFile(sourceFilePath, newFilePath, 0, () => {
20-
resolve(newFilePath);
21-
});
17+
const recover = await rl.question(`你想创建的题目[${newPath}]已经存在,是否覆盖? (Y/N)\n`);
18+
// 如果不覆盖 可以给出两个选择 一个是退出创建进程 一个是创建一个别名
19+
if(!['y',''].includes(recover.toLocaleLowerCase())){
20+
let reconfirm = await rl.question(`是否添加额外内容对题目进行区分,以创建此题目的另外一个解?(Enter/[[$+任意字符]]/N)\n[注:\`$\`符为原题目完整标题,添加额外符号后按\`Enter\`键确认,如不填写直接确认,系统会自动添加\`$[num]\`标识,例如:1.模拟[1]]\n`);
21+
if(reconfirm.toLocaleLowerCase()==="n"){
22+
console.log(`题目[${newPath}]创建终止`)
23+
process.exit()
24+
}
25+
if(reconfirm===""||reconfirm.includes("$")){
26+
// 默认 添加序号
27+
reconfirm||=`$[${getCountBySameName(path.normalize("./src"),newPath)}]`;
28+
const newFileName= reconfirm.replace("$",newPath);
29+
newDir = path.normalize(`./src/${newFileName}`);
30+
newFilePath = path.join(newDir, "index.js")
31+
console.log(`[create]题目[${newPath}]创建副本[${newFileName}]`);
32+
}else{
33+
console.log(`提示:出于安全性和综合情况考虑,请务必按规定格式创建题目,违规题目暂时不予创建。
34+
当前尝试创建题目为:[${reconfirm}]`)
35+
process.exit()
36+
}
37+
}// 如果覆盖 直接进行下一步
38+
}
39+
rl.close()
40+
try {
41+
// 创建目录
42+
fs.mkdir(newDir, { recursive: true }, () => {
43+
// 复制文件
44+
fs.copyFile(sourceFilePath, newFilePath, 0, () => {
45+
resolve(newFilePath);
2246
});
23-
} catch (error) {
24-
reject('[createQuestion]Error:', error.message);
25-
}
47+
});
48+
} catch (error) {
49+
reject('[createQuestion]Error:', error.message);
2650
}
2751
})
2852
})

common/utils/fulfillQuestion.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const fulfillQuestion = (questionPath, question) => {
1212
fs.readFile(questionPath, 'utf8', function (err, data) {
1313
if (err) throw err;
1414
// 修改文件内容
15-
data = data.replace('@题目', `${question.id}.${question.title} [${question.date}]`)
15+
data = data.replace('@题目', `${question.id}.${question.title} ${question.date?"["+question.date+"]":""}`)
1616
.replace("@描述", removeDomTags(question.detail)
1717
.replace("@url",question.url)
1818
.replace(/\n+/g, "\n")

common/utils/getCountBySameName.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
const {readdirSync} = require("fs");
2+
3+
/**
4+
* 根据指定的目录和文件名 给出存在的数量
5+
* @param dir
6+
* @param name
7+
* @returns {number}
8+
*/
9+
function getCountBySameName(dir,name){
10+
return readdirSync(dir).filter(filename=>filename.includes(name)).length;
11+
}
12+
13+
module.exports = {getCountBySameName}

common/utils/getTestCase.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
*/
88
function getTestCase(question){
99
console.log(question)
10-
const cases = question.detail.match(/(<[a-zA-Z]+><\/[a-zA-Z]+>).+\n/g)?.map(str=>`[${str?.replace(/<[a-zA-Z]+>/gm,"")?.replace(/<\/[a-zA-Z]+>/,"")?.replace("\n","")}]`)
11-
const expires = question.detail.match(/(<[a-zA-Z]+><\/[a-zA-Z]+>).+\n/g)?.map(str=>str?.replace(/<[a-zA-Z]+><\/[a-zA-Z]+>/gm,"")?.replace("\n",""))
10+
const detail = question.detail.replaceAll("`","");
11+
const cases = detail.match(/(<[a-zA-Z]+>)?(<\/[a-zA-Z]+>)?.+\n/g)
12+
?.map(str=>`[${str?.replace(/(<[a-zA-Z]+>)?/gm,"")?.replace(/(<\/[a-zA-Z]+>)?/,"")?.replace("\n","")}]`)
13+
const expires = detail.match(/(<[a-zA-Z]+>)?(<\/[a-zA-Z]+>)?.+\n/g)
14+
?.map(str=>str?.replace(/(<[a-zA-Z]+>)?(<\/[a-zA-Z]+>)?/gm,"")?.replace("\n",""))
1215
const functionName = question.jsCode?.match(/var.+=/g)?.[0]?.replace("var ","")?.replace(" =","");
1316
return `showLogs(
1417
${functionName},

common/utils/removeDomTags.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@
44
* @returns {string|string}
55
*/
66
function removeDomTags(input) {
7-
return input.replace(/<[^>]*>/g, '').replaceAll(" "," ").replaceAll("&nbsp;", " ").replaceAll("&lt;", "<").replaceAll("&gt;", ">");
7+
return input.replace(/<[^>]*>/g, '')
8+
.replaceAll(" "," ")
9+
.replaceAll("&nbsp;", " ")
10+
.replaceAll("&lt;", "<")
11+
.replaceAll("&gt;", ">")
12+
.replaceAll("`", "");
813
}
914

1015
module.exports = { removeDomTags }

src/100.same-tree/index.js

-48
This file was deleted.

0 commit comments

Comments
 (0)