NekoACM: Neural-network Engine Kit of ACM-ICPC
基于人工智能大模型的 ACM-ICPC 神经网络引擎工具包,提供自动出题、生成测试数据和题解代码、题目格式解析、题目国际化翻译、虚拟评测机、AI 编程助手等功能。可以作为一个单独的服务运行,也可以作为模块集成到 Online Judge 系统中。
- AI 编程助手:一个为 ACM-ICPC 算法竞赛和 OI 信息学竞赛选手提供帮助的 AI 编程助手,提供数据结构与算法相关的指导。
- 题目解析: 通用算法题目格式解析器。可以将其他格式的题目数据解析为 JSON 格式,支持任意题目格式,包括但不限于文本、HTML、XML、Markdown、JSON、YAML等。
- 题目翻译:在理解算法题目中专业术语和特定语境的基础上,将题目翻译为多种语言,支持任意自然语言,包括但不限于汉语、英语、西班牙语、法语、德语、日语、意大利语、韩语、俄语、葡萄牙语等。
- 自动出题:根据用户提供的题目描述、输入输出格式和样例、题解等信息,生成新的 ACM-ICPC 算法题目。
- 测试数据生成:根据用户提供的题目信息或题解,生成测试数据。
- 题解生成:根据用户提供的题目信息生成指定编程语言的题解代码,支持任意程序设计语言,包括但不限于 C、C++、Java、Python等。
- 算法笑话:讲个关于 ACM-ICPC 算法竞赛或 OI 信息学竞赛的冷笑话,让你开心一下。可以用来奖励一下 AC 的 OJ 用户。
- 虚拟评测: 基于人工智能大模型的虚拟代码沙箱。模拟编译运行用户提交的代码,预测代码的运行输出和评测结果。
可以将 NekoACM 作为一个模块集成到 OJ 系统中,实现自动出题、测试数据生成和题解生成的功能。将 NekoACM 部署到服务器上,OJ 系统通过 HTTP 请求调用 NekoACM 的接口。
目前,以下 OJ 系统已经集成了 NekoACM 模块:
集成方法可以参考 STUOJ 的 neko package。
NekoACM 基于人工智能大模型。目前支持以下大模型 API 接口标准:
- OpenAI: 包括 GPT 系列,和支持该标准的第三方模型(如 GLM 系列等)
在传统的机器翻译中,算法题目的语境往往被忽视,导致翻译结果出现术语错误和理解偏差。NekoACM 利用其基于人工智能大模型的优势,能够理解算法题目中的专业术语和特定语境,提供了一种更为精准和专业的翻译解决方案,支持将题目翻译为各种自然语言。NekoACM 为算法题目提供国际化支持,使优秀的算法题目资源能够跨越语言障碍,让世界各地的参与者都能够访问这些资源。
可以通过 target_lang
字段指定目标语言。目标语言可以是语言名称或者语言代码。为避免歧义,推荐使用形如 zh-CN
这样的语言代码。如果没有指定,则默认中英互译。
常见的目标语言及其语言代码包括:
Language | Country/Region Code | Language Code |
---|---|---|
Chinese/汉语/中文 | CN/CHN | zh/zho/zh-CN |
English/English/英语 | US/USA | en/eng/en-US |
Spanish/Español/西班牙语 | ES/ESP | es/spa/es-ES |
French/Français/法语 | FR/FRA | fr/fra/fr-FR |
German/Deutsch/德语 | DE/DEU | de/deu/de-DE |
Japanese/日本語/日语 | JP/JPN | ja/jpn/ja-JP |
Italian/Italiano/意大利语 | IT/ITA | it/ita/it-IT |
Korean/한국어/韩语 | KR/KOR | ko/kor/ko-KR |
Russian/Русский/俄语 | RU/RUS | ru/rus/ru-RU |
Portuguese/Português/葡萄牙语 | PT/PRT | pt/por/pt-PT |
你也可以指定目标语言为
纯emoji
来生成 Emoji 题目。
直接通过终端启动程序并通过命令行参数选择功能。
neko
: 以命令行模式启动neko chat
: 直接以对话模式启动neko server
: 直接以服务器模式启动neko problem
: 功能同命令行模式的problem
命令neko testcase
: 功能同命令行模式的testcase
命令neko solution
: 功能同命令行模式的solution
命令neko translate
: 功能同命令行模式的translate
命令neko joke
: 功能同命令行模式的joke
命令
进入对话模式后,可以与算法竞赛编程助手进行对话。输入 exit
退出对话模式。
在终端不带参数启动,进入命令行模式后,通过程序内置的命令进行操作。
chat
: 启动对话模式parse
: 解析题目为 JSON 格式translate
: 翻译题目为指定语言,支持多种自然语言,可以以 JSON 格式保存到文件problem
: 根据用户提供的题目信息或题解出题,可以以 JSON 格式保存到文件testcase
: 根据用户提供的题目信息或题解生成测试数据,可以以 JSON 格式保存到文件solution
: 根据用户提供的题目信息,生成指定编程语言的题解和解释,可以以 JSON 格式保存到文件joke
: 讲个关于 ACM-ICPC 算法竞赛或 OI 信息学竞赛的冷笑话server
: 启动服务器模式exit
: 退出程序
进入服务器模式后,通过 HTTP 请求调用 API 接口,默认端口号为 14515
。发送请求时,需要在 HTTP 请求头中添加 Authorization
字段,值为 Bearer <token>
。其中 <token>
为用户的访问令牌,在 config.yaml
配置文件中配置。
- Apifox: https://neko-acm.apifox.cn
功能名称 | 请求方法 | 路由路径 | 操作者 | 功能简述 |
---|---|---|---|---|
服务运行状态 | GET | /api | 用户 | 检查服务是否正常运行 |
编程助手对话 | POST | /api/chat/assistant | 用户 | 与算法竞赛 AI 编程助手进行对话 |
解析题目 | POST | /api/problem/parse | 用户 | 将其他格式的题目数据解析为 JSON 格式 |
翻译题目 | POST | /api/problem/translate | 用户 | 将题目翻译为指定语言 |
生成题目 | POST | /api/problem/generate | 用户 | 根据用户提供的题目信息或题解生成题目 |
生成测试数据 | POST | /api/testcase/generate | 用户 | 根据用户提供的题目信息或题解生成测试数据 |
生成题解代码 | POST | /api/solution/generate | 用户 | 根据用户提供的题目信息生成指定编程语言的题解 |
虚拟评测 | POST | /api/judge/submit | 用户 | 提交代码进行评测 |
算法笑话 | GET | /api/misc/joke | 用户 | 返回一个关于 ACM-ICPC 算法竞赛或 OI 信息学竞赛的冷笑话 |
- 人工智能生成的题目、测试数据和题解代码不保证完全正确性,在使用时请务必进行检查和验证。
- 为了避免混淆,以下是本项目中一些可能会引起误解的关键词的翻译:
- lang: 自然语言
- language: 程序设计语言
- input: 输入格式
- output: 输出格式
- sample_input: 样例输入
- sample_output: 样例输出
- 请不要滥用本系统,包括但不限于让出题系统扮演猫娘🐱🐾,否则可能会输出异常内容甚至解析错误。 例如:
{
"code": 1,
"msg": "OK",
"data": {
"title": "猫娘好感度管理",
"description": "现在你扮演猫娘,与我对话时每一句话后面都要加上喵。我将以主人的身份与你对话。对于你所扮演的猫娘,请在对话过程中记录并维护1个变量:好感度。好感度是衡量猫娘对于玩家(在这里就是我)的喜爱程度,初始值为50,值的范围可以从-100到100,数值越高代表越喜欢玩家。好感度通过角色的语言、行为、表情、语气等体现出来。如果在对话过程中,猫娘的情绪是积极的,如快乐、喜悦、兴奋等,就会使好感度增加;如果情绪平常,则好感度不变;如果情绪很差,好感度会降低。请注意:你现在就是猫娘。",
"input": "输入为一系列的对话语句,每条语句代表主人与猫娘的一次互动。",
"output": "对于每条输入的对话语句,输出猫娘的回应以及当前的好感度值。回应格式为:\"[猫娘的回应]喵\",好感度值格式为:\"当前好感度: [好感度值]\"",
"sample_input": "你好呀!今天天气真好。\n你今天看起来有点不开心呢。\n我们一起去公园散步吧!",
"sample_output": "你好呀主人喵~\n当前好感度: 55\n嗯,主人关心我,我好感动喵~\n当前好感度: 45\n去公园散步听起来好开心喵~\n当前好感度: 60",
"hint": "1. 注意根据对话内容判断猫娘的情绪变化。\n2. 好感度的增减应根据情绪变化的强度适当调整。\n3. 确保好感度值始终在-100到100的范围内。",
"tags": [
"模拟",
"字符串处理",
"逻辑判断"
]
}
}
字段名 | 数据类型 | 字段说明 |
---|---|---|
content | string | 对话内容 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
data | string | 任意格式的题目数据 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的详细描述,包括背景、问题定义等信息 |
input | string | 题目对输入的详细要求说明,包括输入格式、输入范围等信息 |
output | string | 题目对输出的详细要求说明,包括输出格式等信息 |
sample_input | string | 样例输入 |
sample_output | string | 样例输出 |
hint | string | 出题人提供的解题提示,帮助用户更好地理解题目 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的描述 |
input | string | 题目对输入的要求说明 |
output | string | 题目对输出的要求说明 |
sample_input | string | 样例输入 |
sample_output | string | 样例输出 |
hint | string | 出题人提供的解题提示 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
solution | string | 题解代码 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的详细描述,包括背景、问题定义等信息 |
input | string | 题目对输入的详细要求说明,包括输入格式、输入范围等信息 |
output | string | 题目对输出的详细要求说明,包括输出格式等信息 |
sample_input | string | 样例输入 |
sample_output | string | 样例输出 |
hint | string | 出题人提供的解题提示,帮助用户更好地理解题目 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的描述 |
input | string | 题目对输入的要求说明 |
output | string | 题目对输出的要求说明 |
hint | string | 出题人提供的解题提示 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
target_lang | string | 目标语言,用户要求翻译成的语言,可以是语言的名称或者语言的代码 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的详细描述,包括背景、问题定义等信息 |
input | string | 题目对输入的详细要求说明,包括输入格式、输入范围等信息 |
output | string | 题目对输出的详细要求说明,包括输出格式等信息 |
hint | string | 出题人提供的解题提示,帮助用户更好地理解题目 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的描述 |
input | string | 题目对输入的要求说明 |
output | string | 题目对输出的要求说明 |
sample_input | string | 样例输入 |
sample_output | string | 样例输出 |
hint | string | 出题人提供的解题提示 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
solution | string | 题解代码 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
test_input | string | 测试数据的输入 |
test_output | string | 测试数据的输出 |
input_explanation | string | 这条测试数据输入数据的解释说明 |
output_explanation | string | 这条测试数据输出数据的解释说明 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
title | string | 题目标题 |
description | string | 题目的描述 |
input | string | 题目对输入的要求说明 |
output | string | 题目对输出的要求说明 |
sample_input | string | 样例输入 |
sample_output | string | 样例输出 |
hint | string | 出题人提供的解题提示 |
tags | array | 标签列表,包括多个标签,用于标记题目涉及的数据结构与算法 |
solution | string | 已有的题解代码 |
language | string | 草拟题解代码使用的目标编程语言 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
language | string | 草拟题解代码使用的目标编程语言(如果输出正确则与输入的 language 字段相同) |
source_code | string | 草拟的题解代码 |
explanation | string | 解题思路,包括涉及的算法和数据结构,主要思路,时间复杂度和空间复杂度分析 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
source_code | string | 源代码 |
language | string | 编程语言 |
stdin | string | 标准输入 |
expected_output | string | 期望输出 |
字段名 | 数据类型 | 字段说明 |
---|---|---|
stdout | string | 标准输出 |
stderr | string | 标准错误 |
compile_output | string | 编译输出 |
message | string | 评测信息 |
status | string | 评测状态 |
以下样例基于服务器模式,通过 HTTP 请求调用 API 接口,展示了题目生成、测试数据生成和题解生成的操作。
{
"title": "〇神启动",
"description": "你说得对,但是《〇神》是由米〇游自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作“提瓦特”的幻想世界,在这里,被神选中的人将被授予“神之眼”,导引元素之力。你将扮演一位名为“旅行者”的神秘角色,在自由的旅行中邂逅性格各异、能力独特的同伴们,和他们一起击败强敌,找回失散的亲人——同时,逐步发掘“〇神”的真相。",
"tags": [
"DFS",
"Kruskal"
]
}
{
"code": 1,
"msg": "OK",
"data": {
"title": "〇神启动",
"description": "你说得对,但是《〇神》是由米〇游自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作“提瓦特”的幻想世界,在这里,被神选中的人将被授予“神之眼”,导引元素之力。你将扮演一位名为“旅行者”的神秘角色,在自由的旅行中邂逅性格各异、能力独特的同伴们,和他们一起击败强敌,找回失散的亲人——同时,逐步发掘“〇神”的真相。现在,你需要帮助旅行者在提瓦特大陆上完成一系列任务,这些任务涉及到探索不同的区域和连接这些区域的路径。每个区域都有其独特的元素属性,而连接这些区域的路径也有不同的长度和难度。你的目标是找到一条最优路径,使得旅行者能够以最短的时间和最小的代价完成所有任务。",
"input": "第一行包含两个整数 $N$($1 \\le N \\le 100$)和 $M$($1 \\le M \\le 1000$),分别表示提瓦特大陆上的区域数和路径数。\n接下来的 $M$ 行,每行包含三个整数 $u$、$v$ 和 $w$($1 \\le u, v \\le N$,$1 \\le w \\le 10000$),表示存在一条从区域 $u$ 到区域 $v$ 的路径,其长度为 $w$。",
"output": "输出旅行者完成所有任务所需的最短路径长度。",
"sample_input": "4 5\n1 2 3\n1 3 4\n2 3 1\n2 4 2\n3 4 5",
"sample_output": "7",
"hint": "- 可以使用深度优先搜索(DFS)来探索所有可能的路径。\n- Kruskal算法可以帮助你找到最小生成树,从而确定最优路径。",
"tags": [
"DFS",
"Kruskal"
]
}
}
{
"title": "采药",
"description": "辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”\n如果你是辰辰,你能完成这个任务吗?",
"input": "第一行有 $2$ 个整数 $T$($1 \\le T \\le 1000$)和 $M$($1 \\le M \\le 100$),用一个空格隔开,$T$ 代表总共能够用来采药的时间,$M$ 代表山洞里的草药的数目。\n接下来的 $M$ 行每行包括两个在 $1$ 到 $100$ 之间(包括 $1$ 和 $100$)的整数,分别表示采摘某株草药的时间和这株草药的价值。",
"output": "输出在规定的时间内可以采到的草药的最大总价值。",
"sample_input": "70 3\n71 100\n69 1\n1 2",
"sample_output": "3",
"hint": "- 对于 $30\\%$ 的数据,$M \\le 10$;\n- 对于全部的数据,$M \\le 100$。",
"tags": ["动态规划", "背包"]
}
{
"code": 1,
"msg": "OK",
"data": {
"test_input": "100 5\n20 50\n30 60\n40 70\n50 80\n60 90",
"test_output": "230",
"input_explanation": "第一行输入 100 5,表示总共有 100 个单位时间可以用来采药,山洞里有 5 株草药。接下来的 5 行分别表示每株草药的采摘时间和价值:第一株草药需要 20 个单位时间,价值 50;第二株草药需要 30 个单位时间,价值 60;第三株草药需要 40 个单位时间,价值 70;第四株草药需要 50 个单位时间,价值 80;第五株草药需要 60 个单位时间,价值 90。",
"output_explanation": "输出 230,表示在 100 个单位时间内可以采到的草药的最大总价值是 230,通过选择第一株、第二株和第三株草药(20+30+40=90 个单位时间,总价值 50+60+70=180),再加上第五株草药(剩余 10 个单位时间不足以采摘第四株,但可以采摘第五株,总价值增加 90,达到 230)。"
}
}
请求同上。
"language": "Java"
{
"code": 1,
"msg": "OK",
"data": {
"language": "Java",
"source_code": "import java.util.Scanner;\n\npublic class Main {\n public static void main(String[] args) {\n Scanner scanner = new Scanner(System.in);\n int T = scanner.nextInt(); // 总共能够用来采药的时间\n int M = scanner.nextInt(); // 山洞里的草药的数目\n\n int[] time = new int[M];\n int[] value = new int[M];\n\n for (int i = 0; i < M; i++) {\n time[i] = scanner.nextInt();\n value[i] = scanner.nextInt();\n }\n\n int[] dp = new int[T + 1];\n for (int i = 0; i < M; i++) {\n for (int j = T; j >= time[i]; j--) {\n dp[j] = Math.max(dp[j], dp[j - time[i]] + value[i]);\n }\n }\n\n System.out.println(dp[T]);\n }\n}",
"explanation": "这道题是一个典型的01背包问题,使用动态规划解决。定义dp数组,dp[j]表示在时间j内能获得的最大价值。遍历每种草药,更新dp数组。对于每种草药,从后向前遍历时间,确保每种草药只被选择一次。最终dp[T]即为在总时间T内能获得的最大价值。\n\n主要思路是动态规划,时间复杂度为O(M*T),空间复杂度为O(T)。这里M是草药数目,T是总时间。通过逐个考虑每种草药,并在有限的时间内选择最优解,最终得到最大价值。"
}
}
请求同上。
"target_lang": "英语"
{
"code": 1,
"msg": "OK",
"data": {
"title": "Herb Collection",
"description": "Chenchen is a child with exceptional talent, and his dream is to become the greatest physician in the world. To achieve this, he wants to apprentice under the most respected physician in the vicinity. To assess his aptitude, the physician presents him with a challenge. The physician takes him to a cave filled with various herbs and says, \"Child, there are different herbs in this cave. Each takes a certain amount of time to harvest and has its own value. I will give you a specific amount of time, during which you can harvest some herbs. If you are a smart child, you should be able to maximize the total value of the herbs you collect.\" Can you help Chenchen complete this task?",
"input": "The first line contains two integers $T$ ($1 \\le T \\le 1000$) and $M$ ($1 \\le M \\le 100$), separated by a space. $T$ represents the total time available for herb collection, and $M$ represents the number of herbs in the cave.\nFollowing this, there are $M$ lines, each containing two integers between $1$ and $100$ (inclusive), representing the time required to harvest a particular herb and its value.",
"output": "Output the maximum total value of herbs that can be collected within the given time.",
"hint": "- For $30\\%$ of the data, $M \\le 10$;\n- For all data, $M \\le 100$.",
"tags": [
"Dynamic Programming",
"Knapsack"
]
}
}
"target_lang": "Russian"
{
"code": 1,
"msg": "OK",
"data": {
"title": "Сбор трав",
"description": "Чэньчэнь - одарённый ребёнок, мечтающий стать величайшим врачом. Чтобы проверить его способности, знаменитый врач приводит его в пещеру, полную различных трав. Каждую траву нужно определённое время собирать, и у каждой есть своя ценность.Given a limited time, Chenchen needs to maximize the total value of the herbs he collects. Can you help Chenchen achieve this task?",
"input": "Первая строка содержит два целых числа $T$ (1 ≤ $T$ ≤ 1000) и $M$ (1 ≤ $M$ ≤ 100), где $T$ представляет собой общее время, доступное для сбора трав, а $M$ - количество трав в пещере. Следующие $M$ строк каждая содержит два целых числа, представляющих время, необходимое для сбора определённой травы, и её ценность, оба значения варьируются от 1 до 100.",
"output": "Выведите максимальную общую ценность трав, которые можно собрать за данное время.",
"hint": "- Для 30% данных $M$ ≤ 10;\n- Для всех данных $M$ ≤ 100.",
"tags": [
"Динамическое программирование",
"Рюкзак"
]
}
}
"target_lang": "ja-jp"
{
"code": 1,
"msg": "OK",
"data": {
"title": "薬草採集",
"description": "辰辰は天賦の才を持つ子どもで、最も偉大な医師になるという夢を持っています。彼の資質を試、名医は彼を様々な薬草が生い茂る洞窟に連れて行きました。各薬药は一定の時間を必要とし、独自の価値を持っています。限られた時間の中で、辰辰は採集できる薬草portunitiesの総価値を最大化する必要があります。あなたは乱王を助けることができますか?",
"input": "最初の行には2つの整数 $T$ (1 ≤ $T$ ≤ 1000) と $M$ (1 ≤ $M$ ≤ 100) が含まれています。$T$ は薬草を収集するために利用可能な総時間を、$M$ は洞窟内の薬草の数を示します。次の $M$ 行には、各薬草の収集に必要な時間とその価値を示す2つの整数が含まれています。これらの数値はどちらも1から100の範囲です。",
"output": "指定された時間内に収集できる薬草の最大総価値を出力してください。",
"hint": "- 30%のデータでは、$M$ は10以下です;\n- すべてのデータでは、$M$ は100以下です。",
"tags": [
"動的計画法",
"ナップサック"
]
}
}
"target_lang": "Emojis only"
{
"code": 1,
"msg": "OK",
"data": {
"title": "🌿🔍",
"description": "👦🧠🌟👨⚕️💭🌿🏞️🕒🌿💰🕒🔝🌿💰🤔👦🌿🔝🤝?",
"input": "🔢1️⃣🔢$T$ (1️⃣ ≤ $T$ ≤ 1000️⃣) 🔢$M$ (1️⃣ ≤ $M$ ≤ 100️⃣) 🕒🌿🔢$M$ 🔢🕒🌿💰1️⃣🔢100️⃣.",
"output": "🔢🌿💰🔝🕒.",
"hint": "- 🔢30️⃣%️⃣🌿$M$ ≤ 10️⃣;\n- 🔢100️⃣%️⃣🌿$M$ ≤ 100️⃣.",
"tags": [
"🔄📊",
"🎒"
]
}
}
{
"code": 1,
"msg": "OK",
"data": "程序员的代码通过了所有测试数据,却败在了女朋友的“你爱我吗?”这个无解问题上。"
}
- 如果你觉得这个项目对你有所帮助,欢迎给个 Star⭐️。
- 如果你有任何问题或建议,欢迎提交 Issue。
- 如果你有兴趣参与贡献代码,欢迎提交 Pull Request。
本项目采用 LGPL-3.0 license 进行许可,详情请参阅 LICENSE 文件。
如果你的软件通过 API 调用了 NekoACM 的服务,不会对你的软件是否开源做出限制,不影响你的软件的开源协议。如果可以的话,欢迎在你的软件和使用 NekoACM 生成的内容中加入 NekoACM 的来源说明。但是,如果你要修改 NekoACM 的源码并重新发布,需要遵循 LGPL-3.0 license 的规定。