OO第一单元历险——表达式求导

开学前十天做了两弹pre(占分啊啊啊),基本熟悉了一下java的语法,没有对象的我就这么开始了面向对象。

第一次作业

这次作业只需要处理幂函数多项式的表达式,写的非常面向过程(从如下度量分析图中也可以看出,尤其Polynomial过于臃肿。。。),教程中给的形式化表述层次性、表达性非常好,便从常数到幂函数再到项,逐步为整个表达式字符串构建正则表达式,以大正则法匹配表达式中的各个项,存入Term中,再将Term集合于一个ArrayList中,再对其求导,以一定规则输出。

(这里我还不太理解捕获组,所以处理过程非常丑陋,给hack我的同学在读代码的过程中造成了非常大的麻烦,深表歉意qaq)

结构分析

总共只有三个类,这里的Main基本只起到了入口、出口的作用;

程序核心在于Polynominal,集解析字符串、提取项、求导、输出等功能于一身(现在看的话完全就可以只写一个Main类。。。),内部有以项Term为元素的ArrayList来存储;

Term类里存储了一个项的系数和指数,便于排序、求导。

 

bug分析

利用Python的Sympy库简单地写了一个验证程序,大概算是半对拍器。。。

在自行测试时,我将测试数据大致分成了若干类,但是在最后提交时忘记将修改后多余的两条语句删去,在互测中被hack了几次,不过毕竟是同质bug(幸免于强测)。

拿着手里的数据也成功hack了几个点。。。

小结

这次作业为后面的两次迭代打下了基础,但因为当时完全没有考虑后面的迭代,导致在做第三次作业的过程中有点难受

第二次作业

这次作业在第一次作业的基础上增加了三角函数作为因子,并需要对输入格式进行判断。

这就是鲜明的大正则法条件啊!!!

于是我在此次作业中重新优化了正则表达式,并将项目写得看起来更加面向对象一些。。。

 

 不过这里Polynomial的复杂度和聚合度还是太高了。

结构分析

相较于第一次作业,这里对结构有了更具体的划分。将由乘号(*)分割的各因子Factor存于Term中,再将由加号(+)分隔的各项Term存于Polynomial中。这里因为考虑到第三次作业的迭代,创建了一个Factor抽象类,将幂函数因子、正弦因子、余弦因子继承于Factor,方便利用多态执行求导、获得各因子指数等方法。

针对输出结果的性能,对求导后的表达式以系数大小排序,进行了三重循环来合并同类项与三角函数的化简。不过由于在解析正则表达式时对原表达式没有预处理化简,导致有的导函数没能化到最简,所以扣了一些性能分。。。

 

bug分析

这次作业因为对正则表达式的捕获组运用更熟练,所以构建的正则表达式层次性也有了体现,在构建测试数据时分类也更加清晰。

在强测和互测中都没被查出bug,也没花时间读别人代码了,交上几个数据也幸运地hack了几次。

小结

做第二次作业时大概了解到第三次作业需要考虑嵌套,自以为大正则法会比较好使。。。

这时大概了解了一些工厂模式,可惜没弄懂,所以就没有运用到第三次作业中。

第三次作业

这次作业加入了表达式因子,在构建正则表达式时会出现递归调用,这就导致想完全沿用第二次作业中的大正则法几乎不可能了,但又有些不舍,于是若即若离中写得很狼狈。

结构分析

相较于第二次作业,基本相当于重构了一遍,使Main作为顶层更具有统筹性。

将原先集解析、存储、求导、输出于一身的Polynomial根据耦合程度和内聚性分成了用来解析表达式的Regex类和用来存储、求导的Polynomial类。

因为增加了表达式因子,原先定义的因子求导后返回的就有可能是表达式而不是因子或项了,所以针对各类FactorTerm进行了改写。以幂函数因子作为底层,根据三角因子和表达式因子括号中的内容来递归调用表达式因子,最终归束到幂函数因子上。

 

bug分析

提交一次通过中测后就没有继续做太多的测试了。结果自己在互测阶段发现了自己的bug——把三角因子括号里的内容简单地和表达式因子归为一类,这就导致在出现cos((x**2))这类测试数据时会将括号里的式子求导时会算两遍。虽然互测中合并修复就vans了,但可惜了强测的分数。。。

由于在互测时看着自己的被hack数不停的增长,内心十分煎熬,于是只能痛下杀手刀了17/54(但没想到房间里还有20/54和47/84的狼人

小结&第一单元幸存心得

很多同学都说这次作业使用树的结构会很好,一方面因为实在不舍,另一方面因为自己没想出来用树的结构怎么合并同类项、怎么化简,所以最后便还是没有建树,或许该重构时还是得坚定一些。。。

猜你喜欢

转载自www.cnblogs.com/kjs001019/p/12513894.html
今日推荐