一 前言
洛谷新增加了文言语言的功能,但是我并没有听说过这玩意……
我折腾了半天,顺便写了这篇文章
二 安装&编译
我推荐使用vscode
进行编译 因为我在用
sublime
也有插件支持 但由于我不用所以暂不介绍(逃 请大家自行研究 谢谢
vim
也被支持了 但是太难所以不介绍 应该没人在用吧~
dev
的同学们难道不觉得dev
很难看吗?当然你可以尝试直接使用命令行编译你的程序,但这会很麻烦,你可以直接在cmd
输入npm install -g @wenyanlang/cli
来安装文言编译器,并输入wenyan
来查看教程
如果你没有npm
的话可以先安装python
,在windows
的python
安装包中可以选择安装npm
linux
或mac
的同学也可以安装vscode
或者sublime
的插件
vscode
真是个好东西啊~,它可以支持python
,C++
甚至支持markdown
预览
进入vscode
的插件商店,搜索wenyan
,第一个就是了,点击install
就可以了
然后会变成这个样子
随便找一段文言代码(后缀为.wy),可以发现右上角多了两个按钮:
第一个按钮是另一个插件的
那个蓝色的代码按钮可以将代码编译成javascript
的代码(编译为python
也可以,只是代码前会多)
那个绿色的运行按钮可以编译运行文言代码
试一试吧
妙啊
三 写代码
我们用洛谷题目举例子吧
首先 你需要把你的输入法调成繁体,怎么调不多叙述
我们来看P1000 超级玛丽游戏
(代码太多 我们只看第一行的输出 文言没有代码高亮抱歉)
吾有一言。曰「「 ********」」。書之。
吾有一言:定义一个字符串,这里没有说明字符串的名字。
曰:相当于定义时的'=' 这里的制表符一个是括号,一个是双引号
如果你使用vscode
的文言插件的话只需按'
键(键盘asd
一行最左边)就可以自动输入这些奇怪的符号了
書之:输出它
文章大意: 我有一句话,是" ",输出它
cout<<" ********";
注: 后面所有因翻译为C++
过于抽象,大多翻译为javascript
语法,少部分直译
我们再来看P1001 A+B Problem
标准代码真烦……
我们先复制下来再看
施「require('fs').readFileSync」於「「/dev/stdin」」。名之曰「數據」。
施「(buf => buf.toString().trim())」於「數據」。昔之「數據」者。今其是矣。
施「(s => s.split(' '))」於「數據」。昔之「數據」者。今其是矣。
注曰。「「文言尚菜,無對象之操作,故需 JavaScript 之语法」」。
夫「數據」之一。取一以施「parseInt」。名之曰「甲」。
夫「數據」之二。取一以施「parseInt」。名之曰「乙」。
加「甲」以「乙」。書之。
先看第一句
施「require('fs').readFileSync」於「「/dev/stdin」」。名之曰「數據」。
施a于b: 相当于a(b)
,将b作为参数传入名为a的函数中
/dev/stdin: 标准输入文件
注意:javascript
并不支持直接从console
读入数据,但是在linux
下,此文件相当于控制台的输入,Windows
则只能使用绝对路径进行本地测试,如C:/users/xxx/desktop/1.in
名之曰……: 将其命名为……
數據: 数据
所以这句相当于(C++
表示已无能为力)
数据=require('fs').readFileSync("/dev/stdin")
看第二句
施「(buf => buf.toString().trim())」於「數據」。昔之「數據」者。今其是矣。
昔之a者。今b是矣: 相当于a=b
这就很好理解了
数据 = (buf => buf.toString().trim())(数据)
将输入转为字符串
看第三句
施「(s => s.split(' '))」於「數據」。昔之「數據」者。今其是矣
没啥说的,分开输入数据成一个数组,和python
的split
操作接近
看第四句
注曰。「「文言尚菜,無對象之操作,故需 JavaScript 之语法」」。
注曰。: 注释
很好理解,就是个注释
第五,六句
夫「數據」之一。取一以施「parseInt」。名之曰「甲」。
夫「數據」之二。取一以施「parseInt」。名之曰「乙」。
夫a之b: 同a[b]
。这里下标不减一
取k以施a: 将刚才列的后k
数作为参数传入名为a
的函数中
不难理解:
甲=parseInt(数据[0])
乙=parseInt(数据[1])
将数据转为整数格式,与python
的int()
类似
最后一句
加「甲」以「乙」。書之。
加a以b: 同a+b
。
不解释。
接下来来看P1046 陶陶摘苹果
输入变成了一串数……
但是没关系,只要稍微处理下即可。
这次分开上代码,完整代码可以看这里
前三句
施「require('fs').readFileSync」於「「C:\\02Cpp\\文言\\dev\\stdin.in」」。名之曰「數據」。
施「(buf => buf.toString().trim())」於「數據」。昔之「數據」者。今其是矣。
施「(s => s.split('\n'))」於「數據」。昔之「數據」者。今其是矣。
老样子,只是因为是两行数据,变成按换行分了
注:也可以用正则表达式input_str.split(/[\s\n]/)
来分割,只是这样无法辨别出哪些数在哪一行
第五句
这里是把输入的第一行拿出来按空格分开成一个数组“甲”。
第六句
凡「甲」中之「數」。
凡a中之b: 枚举a中的每个元素b,注意这里是中之,不是之中
第八句
充a以b: 在a后添加一个元素b
第九句
云云: 可以理解为后面的大括号
第十四,十五,十六句
若……者……也:if(……){……}
其他部分显而易见
其他语法
不用例题做示范。
函数系列
吾有一術。名之曰「吸星大法」。是術曰。⋯⋯是謂「吸星大法」之術也。: 定义一个叫吸星大法的函数
吾有一術。名之曰「翻倍」。欲行是術。必先得一數。曰「甲」。乃行是術曰。乘「甲」以二。名之曰「乙」。乃得「乙」。是謂「翻倍」之術也。: 定义一个有参数的函数
乃得k: return k
吾嘗觀「「算經」」之書。方悟「正弦」「餘弦」之義。: 调用标准库中的函数,具体可见这里
循环系列
为是k
遍: 循环k
遍(k
可替换成百
,十一万四千五百十四
等等)
恒为是: while
循环
乃止: break
其他请看官方语法手册
四 彩蛋
还有一个re掉的并查集代码
求查错
施「require('fs').readFileSync」於「「dev/stdin」」。名之曰「數據」。
施「(buf => buf.toString().trim())」於「數據」。昔之「數據」者。今其是矣。
施「(s => s.split(/[\s\n]/))」於「數據」。昔之「數據」者。今其是矣。
吾有五列。名之曰「輸入」。名之曰「id」。名之曰「n」。名之曰「m」。名之曰「答案」。
吾有二數。曰一。曰一。名之曰「p」。名之曰「tmp」。
吾有五數。名之曰「甲」。名之曰「乙」。名之曰「丙」。名之曰「戊」。名之曰「己」。
凡「數據」中之「數」。
若「數」不等於「「」」者。
夫「數」。取一以施「parseInt」。名之曰「某數」。
充「輸入」以「某數」。
也。
云云。
吾有一術。名之曰「得入」。是術曰。
昔之「p」者。今「p+1」是矣。
夫「輸入」之「p-1」。乃得矣。
是謂「得入」之術也。
吾有一數。名之曰「id之x」。
吾有一術。名之曰「尋」。欲行是術。必先得一數。曰「x」。是術曰。
若「id」之「x」等於「x」者。
乃得「x」。
若非。
夫「id」之「x」。取一以施「尋」。昔之「甲」者。今其是矣。
昔之「id」之「x」者。今「甲」是矣。
夫「id」之「x」。乃得矣。
也。
是謂「尋」之術也。
吾有一術。名之曰「合」。欲行是術。必先得二數。曰「x」。曰「y」。是術曰。
施「尋」於「x」。昔之「甲」者。今其是矣。
施「尋」於「y」。昔之「乙」者。今其是矣。
昔之「id」之「乙」者。今「甲」是矣。
乃歸空無。
是謂「合」之術也。
施「得入」。昔之「m」者。今其是矣。
施「得入」。昔之「n」者。今其是矣。
昔之「甲」者。今一是矣。
為是「m」遍。
充「id」以「甲」。
昔之「甲」者。今「甲+1」是矣。
云云。
注曰。……
為是「n」遍。
施「得入」。昔之「甲」者。今其是矣。
施「得入」。昔之「乙」者。今其是矣。
施「得入」。昔之「丙」者。今其是矣。
若 「甲」等於 一 者。
夫「乙」。夫「丙」。取二以施「合」。
若非
施「尋」於「乙」。昔之「戊」者。今其是矣。
施「尋」於「丙」。昔之「己」者。今其是矣。
若 戊 等於 己 者。
夫「「Y」」。書之。
若非。
夫「「N」」。書之。
也。
也。
云云。
0 条评论