(C103)[Nerovix]BUAA2024春OOの第一单元总结[Chinese][aaub汉化组]

迭代、Hacks与优化

hw1

需求分析

第一次作业要求实现一个仅包含整式的、括号最多嵌套一层的单变量('x')括号表达式化简。要求输出中不能包含括号。

架构与实现

第一次作业相对简单,只是一个预热,但也强度不小。处理表达式化简的问题,需要先理解何为递归下降法。这个方法的核心思想在于,利用表达式的特征结构,把整个表达式逐层向下展开分析,最后得到一个树形的结构,然后再自底向上计算答案。

然而仅是理解了方法,距离落实到代码上还很远。我们需要一个方便简洁的架构来实现我们的构想。参考第一次训练的代码,我设计了外层用LexerParser分析输入的表达式字符串,然后Parser按照表达式的逻辑转化成内部的由ExprTermNumberPow构成的递归下降树形结构,最后再使用多项式类Poly来计算答案这样的结构。

Lexer是最外层的、仅对输入表达式字符串进行词元划分的分析类。根据多项式的格式,我把词元划分成了以下类型:EOF、无符号纯数字、'x^...''('')^...''+''-''*'。如果在'x'')'后没有幂次,手动补全幂次为1保持格式统一。Lexer的核心方法是Lexer.next(),其作用在于分析下一个词元并存放到curToken中,然后向前移动字符串指针。可以调用Lexer.peek()查看curToken

Parser是根据Lexer传递的词元分析生成树形结构的类。在构建此类之前,我先构建了ExprTermNumberPow四个类,分别表示表达式、项、数字、幂函数。其中除Term外的三类都实现了Factor接口,表示他们是因子。Expr包含一个ArrayList<Term>,表示表达式由一些项构成;Parser包含一个ArrayList<Factor>,表示项由若干因子相乘而得。在Parser中,main调用parseExprparseExpr按照构造规则,多次调用parseTermparseTerm又按照构造规则调用parseExprparseNumberparsePow,形成一个互相调用,逐级向下的结构。

最后我使用Poly类计算答案。考虑到第一次作业的答案形式比较固定唯一,一定是一个多项式,所以我构建了Poly多项式类。Poly类包含一个HashMap<Integer, BigInteger>,键表示多项式内项的指数,值表示多项式内项的系数。利用Parser构建表达式树后,直接调用构造函数Poly(Expr)构造答案。其内部会向下递归调用Poly(Term)Poly(Number)Poly(Pow)等其他构造函数,遍历整个表达式树,并实现加法乘法辅助计算。

优化

由于第一次作业答案形式唯一,并且在Poly的计算中已经体现了同类项的合并,所以并没有太多的可优化内容。我实现的唯一优化是找到最终答案中是否有正项,如果有就可以提到最前面,这样可以省下一个符号的长度。

Hacks

第一次作业房间里没有任何成功的hack。

结果

第一次作业顺利获得了满分,互测中也没有被hack。

hw2

需求分析

在第一次作业的基础上,加入了两个新内容:其一为自定义函数,规定定义内部不会嵌套,也就是自定义函数定义内不会有任何自定义函数;其二为加入了指数函数exp()

架构与实现

针对自定义函数,我的解决方法是在最开始就把函数带入表达式中,做字符串替换,不涉及到后面表达式分析与处理。我新建了两个新类FuncFuncKilla,前者内部保存一个函数,包括一个String name表示函数名,一个ArrayList<String>params表示参数,一个String definition表示函数的定义;后者包括一个HashMap<String, Func>存储所有函数,其核心方法为FuncKilla.killFuncs(String input),它接受包含自定义函数的输入,返回消除所有自定义函数后的纯表达式。处理过程中需要注意一些细节,例如自定义函数代入参数时需要加入额外括号,自定义函数本身替换完成后也需要加括号,为了防止出现运算符优先级相关的问题。

针对exp,首先对LexerParser做相应的修改。然后加入Exp类,内部包含一个Expr表示指数上的内容,并实现Factor接口,这与第一次迭代相关内容并无大异。改动最大的部分是Poly部分。虽然此次迭代答案不再一定是多项式,但是我仍然希望沿用第一次迭代求答案的形式。然而,Poly内部不能再用 HashMap<Integer, BigInteger>存储,这就需要另动脑筋。

第一次迭代中,键的Integer表示x^...,考虑到这次有指数函数,我新建了Unit类,包含一个Poly p

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值