2019面向對象程序設計第一單元總結

<font size=6>2019面向對象程序設計第一單元總結</font>java

<font size=5>一.三次做業的設計思路</font>

<font size=4>Ⅰ.僅含常數和冪函數的多項式求導</font>

<font color="red" face="楷體" size="4">(1)思路一:WF判斷與分項結合,避免大正則爆棧問題</font>正則表達式

​ 第一次做業中,多項式的結構具備極強的規律性,因此很多同窗想到用正則表達式匹配整串,但忽略了大正則存在回溯次數過多可能會致使爆棧。所以正確的處理策略之一是,單獨處理輸入中的空格,正負號以及非法字符,而後用正則匹配表達式中的每一項,獲得的全部項相加,若與原表達式不相同,則判爲「WRONG FORMAT!」,不然,則輸出求導結果。express

正則匹配處理空格與符號後的每一項:架構

Pattern pattern = Pattern.compile("([-+]+(([-+]?(\\d+\\*)?x(\\^[-+]?\\d+)?)|([-+]?\\d+)))");

而後用<font color="blue">Matcher</font>中的<font color="blue">find()</font>函數實現分離每一項,用<font color="blue">Matcher</font>中的<font color="blue">group()</font>函數實現項處理。函數

<font color="red" face="楷體" size="4">(2)思路二:用ArrayList、LinkedList或HashMap實現動態插入新項</font>測試

​ 筆者在第一次做業中採用的是利用泛型的LinkedList實現優化

public class PolyHandler {
    //利用鏈表構造求導後的新多項式
    private LinkedList<String[]> polynomial;
    
    //構造函數
    PolyHandler(LinkedList<String[]> polynomial) {
        this.polynomial = polynomial;
    }

重點:在動態添加元素的過程當中,實現同類項的合併,可以大大減小優化複雜度。this

​ 筆者利用PolyHandler類中的merge函數實現求導後多項式合併新項spa

void merge(String[] item)

下圖爲第一次做業個人類圖設計

StringMatcher用於初步判斷輸入是否合法

ItemHandler爲項處理類

PolyHandler爲多項式處理類

MainHandler爲主類

<font size=4>Ⅱ.僅含常數、冪函數和三角函數的多項式求導</font>

<font color="red" face="楷體" size="4">(1)思路一:本次做業仍可利用正則進行分項</font>

​ 筆者認爲,第二次做業相比第一次多項式求導做業而言,在處理非法輸入與求導方面對總體架構的改變不大,所以筆者沿用了第一次做業的設計,複用了較多的類。

​ 正則分項:

Pattern pattern = Pattern.compile("[-+](\\d+|(x(\\^[-+]?\\d+)?)|" +
                "(sin\\(x\\)(\\^[-+]?\\d+)?)|(cos\\(x\\)(\\^[-+]?\\d+)?))" +
                "(\\*[-+]?(\\d+|(x(\\^[-+]?\\d+)?)" +
                "|(sin\\(x\\)(\\^[-+]?\\d+)?)|(cos\\(x\\)(\\^[-+]?\\d+)?)))*");

emmm......看上去是否是很複雜呢,在第二次做業咱們已經能夠上遞歸降低分析了!

<font color="red" face="楷體" size="4">(2)思路二:用HashMap處理多個Key,化簡時有巨大優點</font>

​ 自定義一個類,包含多個Key,將這個類做爲HashMap的Key類型,並實現這個類的哈希函數和相等性斷定函數。

1.哈希函數

int hashcode()

2.相等性斷定函數

boolean equals(object obj)

下圖是筆者本身設計的HashKey類中重寫的核心方法

注:在第二次做業中,利用HashMap實現同類項的合併相比ArrayList與LinkedList有更大優點。

下圖爲我第二次做業的類圖

​ StringMatcher類用於判斷輸入是否合法

​ HashKey類爲本身設計構造的HashMap的Key類型

​ Expression類爲表達式處理類

​ Item類爲項處理類

​ Derivation類爲求導類

<font size=4>III.包含常數、項、冪函數與嵌套三角冪函數多項式的求導</font>

<font color="red" face="楷體" size="4">核心思想——遞歸降低分析法:表達式由項構成,項由因子構成,因子的種類能夠是表達式,冪函數,常數項,三角函數類。</font>

1.表達式:讀取項,用LinkedList存儲項:

LinkedList<Term> parseExpression()

2.項:讀取因子,用LinkedList存儲因子:

Term parseTerm()

3.因子

//外包函數,分析因子種類,而後分種類爬取因子
Factor parseFactor()
//獲取常數項因子
Factor getConstantFactor()
//獲取冪函數因子
Factor getXFactor()
//獲取正弦函數因子
Factor getSinxFactor()
//獲取餘弦函數因子
Factor getCosxFactor()
//獲取表達式因子
Factor getExpressionFactor()

爲使邏輯清晰,可把因子種類定義爲枚舉類型。

public enum FactorType {
    constant,x,sin,cos,expression
}

下圖爲第三次做業個人類圖

​ StringMatcher類用於判斷輸入格式是否爲正確格式

​ Expression類爲表達式處理類

​ Term類爲項處理類

​ Factor類爲因子處理類

​ FactorType枚舉類型定義了因子類型

<font size=5>二.優化策略簡介</font>


筆者會在另外一篇博文中對優化策略進行詳解,在此僅說下總體思路。</u>

題外話,筆者在三次做業的優化中均取得了還不錯的成績,第一次做業滿分,第二次做業第11名,第三次做業前10名

<font color ="lightgreen">1).第一次做業優化要點:</font>

①合併同類項

②正項前移

<font color ="lightgreen">2).第二次做業優化要點:</font>

①合併同類項

②利用三角函數公式簡化(主要採用瞭如下四類公式):

1°  sin(x)^2 + cos(x)^2 = 1

​			2° 1-sin(x)^2 = cos(x)^2

​			3° 1-cos(x)^2 = sin(x)^2

​			4° sin(x)^4 - cos(x)^4 = sin(x)^2 - cos(x)^2

③正項前移

<font color="lightgreen">3).第三次做業優化要點:</font>

​ 筆者認爲,第三次做業的優化重點不在於利用三角函數公式簡化,而在於在可控時間複雜度下利用遞歸降低實現同類項的合併,這便須要重寫Expression類、Term類、Factor類的hashcode()和equals()函數

<font size=5>三.綜合三次做業的方法複雜度的分析</font>


第一次做業:

第二次做業:

第三次做業:

​ 能夠看出,隨着三次做業的層層遞進,工程的方法數目與方法複雜度均在上升。因爲2、三次做業的優化相對複雜,故我在相應的類中實現了較多複雜度較高的方法來進行相應的優化,具體方法邏輯可參考類圖。

<font size=5>四.Bug分析</font>


​ 三次做業個人強測所有經過,均沒有出現bug,加上優化分,筆者在三次做業中的強測得分分別爲100分、99.2839分、96.7647分。

​ 但在第三次做業中,我被別的玩家hack了一個點,系我在化簡過程當中一個if語句判斷失誤,去除了三角函數中表達式因子的括號,致使輸出格式有問題。這也告誡我,在優化過程當中,必定要考慮全面。

<font size=5>五.高效Debug和Hack策略分析</font>


筆者認爲,其實要想成爲OO互測的頂級玩家,必需要擁有一臺本身編寫的評測機,千萬不要偷懶。

<font color="red" face="楷體" size="4">(1)構建本身的「強測」評測機(全面覆蓋):</font>

① 自動生成隨機表達式串

② 讓本組成員的程序互拍,尋找不一樣結果。

③ 判斷錯誤結果的來源、錯誤結果的種類(即Wrong Format Error、Wrong Value Error仍是Wrong Derivative Error),並輸出到指定文件

​ 下圖是用Python實現的第三次做業的評測機。

<font color="red" face="楷體" size="4">(1)精心構造測試樣例(重點針對):</font>

​ 評測機生成的數據太隨機,所以每每有些bug會疏漏掉,須要本身讀懂評測屋內的代碼,並分析其架構和邏輯上的失誤,並構造相應樣例。

​ 好比第二次做業的一個針對優化的典型hack樣例:

x*sin(x)^4*cos(x)^-4+x*sin(x)^5*cos(x)^-5+x*sin(x)^2*cos(x)^-2+x*cos(x)^-3+x*sin(x)^6*cos(x)^-6

​ 第三次做業的一個典型hack樣例

cos((((-+((((sin(x)))))))))

<font size=5>六.Applying Creational Pattern</font>


​ 工廠模式與抽象工廠

​ 對於本次做業可使用工廠模式來建立表達式,項,因子,咱們只需定義一個建立對象的接口,讓實現了該接口的子類本身決定實例化哪個工廠類。在咱們明確地計劃不一樣條件下建立不一樣實例時,工廠模式將十分管用。

​ 抽象工廠模式是圍繞一個超級工廠建立其餘工廠。在抽象工廠模式中,接口是負責建立一個相關對象的工廠,不須要顯式指定它們的類。每一個生成的工廠都能按照工廠模式提供對象,這樣咱們就不用花費時間在選擇接口上了。

<font size=5>七.總結與展望</font>


​ 北航的OO課正在不斷變好,感謝老師、助教和爲其餘爲這門課默默付出的人。我會再接再礪,不斷提高本身的分析能力和代碼能力。

相關文章
相關標籤/搜索