一.概述

第一单元的作业主要内容为表达式解析与化简,由于寒假预习不充分,我在一开始就采用了预解析模式,所以代码结构较简单,在整个迭代开发过程中基本没有经历过大的重构;

二.三个task

  1. task1

  第一次作业的因子只有常数和、x以及函数变量fi,共有六种操作符:add,sub,pow,mul,pos,neg ,为此我设计了以下两个类:Fi,Item。

  Item是项,代表着ax^i,有系数a和指数i两个参数。重写了判断两个项是否相等的方法。

  Fi是一个 Item的容器,以及有一个int型变量i,i是用来找到指定的Item容器的,Fi中有add,sub,pow,mul,pos,neg,以及collect方法(用来合并同类项)。add、sub实现方式类似,将Item Addall起来(sub只用将所有的Item的系数取相反数即可),然后将这个新建容器输入collet方法即可。mul方法设计两个循环,将第一个Fi每个Item遍历乘第二个Item一遍,然后交给collect统一合并同类项。

  

 

 

 

  每次从预解析中读入一行,有三种情况:1.只有操作数,如(f1 1);2.有一个操作数以及一个操作符(f1 neg 2);3.有两个操作数和一个操作符,如(f2 add f1 x)。读入时以空格分割开,然后将所有的操作数转换为fi的形式(如操作数1,先将转化为1x^0,转化为一个Item,再建立一个Item容器,里面只有一个Item)。再通过对fi分别进行add,sub,pow,mul,pos,neg即可。

  在化简部分,我设计了一个collect方法,输入为一个Item的容器,先新建一个Item的Arraylist,每次读入一个Item,然后再在容器中找是否有这个元素,如果有,则将该Item的系数相加,如果没有,则创建一个新的Item加入Arraylist中。这里会出现一个深克隆和浅克隆的问题。加入直接将Item以等号的方式进行赋值,那么当在修改collect输出时的系数时,原有的系数也会产生变化,例如我们直接赋值a = b ;那对a的参数进行修改时,b的参数也会发生改变,而这不是我们所希望出现的。为了防止这种干扰造成的bug,一种做法是采用深克隆,当你需要两个互不干扰的列表时,需要递归地拷贝里面的所有元素。另一种方式是将Item变成不可变对象,将系数设置为私有对象并不提供setter方法,该对象自创建起内容便不会发生变化。此时你需要两个不会互相干扰的ArrayList时,也可以直接对ArrayList不进行深克隆。

  输出方面,我简化了系数为零(也就是只是常数)、系数为零不输出的情况。但是,我的零是不输出的,并没有判断是否只有一项,因此就会出现x-x出现没有输出的情况。

  2 .task2,3

   有了task1的结构,task2操作就很简单了。只需添加三个类:sin,cos,powfunction。其中,powfunction替代原有的item,sin,cos参数powfunction类,以及三角函数的指数。item

变为一个powfunction,一个sin容器和一个cos容器即可。在操作时只需要加上sin和cos两个操作符就可以了。

 

 

 

   有了task2的结构,task3更加简单。只需将sin和cos的参数变为一个Fi,其他基本不变即可。

   在task2和task3的优化方面,我主要做了将三角函数内的Fi中Arraylist<Item>相同的进行合并,然后合并同类项,实现方法与上文类似。只是在判断同类项时需要重写equals的方法,在未重写前,只是简单的比较地址是否相等,而重写了以后,则可以比较其中的内容。

  3.数据构造

   在对自己程序进行验证或对其他人进行Hack时,首先需要仔细阅读指导书,确保自己对于指导书中的细节完全了解,避免被强测背刺,比如笔者在第二次作业中,疏忽了在函数定义中可以存在空格,导致解析错误。对于黑盒测试,笔者认为可采取两种方式对程序进行验证和Hack,一是数据生成器随机轰炸,这种可以找出程序中基本的错误;二是对一些极端情况的数据构造,比如因子0次幂指标溢出。对于白盒测试,主要通过代码分析来找出程序中的漏洞,比如如果对方采取了正则表达式解析,则可以重点关注其表达式的书写是否有纰漏;如果对方进行复杂的优化,则可以重点关注优化部分的逻辑是否正确,是否可能发生TLE。

 

三. 总结

    在小组讨论过程中,我们组尤其讨论了撰写博客的意义所在,其中一大讨论结果就是“积累经验”。经验一次看似一笔带过般简单,但事实上却浓缩着整个大脑的抽象工作。它负责将我们所学的知识串联起来,并抽象成一块块有关系有结构的树型知识链,尽管日后我们不一定记得详细的知识点,但是却能联想到这方面的主要思想和易出错点,知识点忘了可以重新查找,但是“经验”在未来做项目时扮演者极其重要的角色。当然,这样说并不意味着知识点不重要,能记住知识点固然更好,只不过我认为经验更为重要。

    经过这三周的学习,最大的收获还是文前所言的两个课程特征,这也是课程对我们提出的要求。如何能在一周为数不多的大段时间内,从设计到实现一个解决问题的方案,不仅考验知识,更是考验能力。我们需要合作,我们不仅要有自己的想法,更要善于学习他人想法,并在此过程中改善自己的想法,这样才能锻炼出短时间内得出最佳方案的能力;我们需要想清楚再动手,这个阶段才是最耗费时间的,如果将架构设计好之后,bug会少,重构会少,可谓一劳永逸。

    本月的oo做的比较仓促,导致在写完之后并没有花很多时间进行测评。导致出现了一些很低级的bug。在下次的作业中多构造数据进行测评,会取得更多的分。