結對編程 – 計算最長英語單詞鏈
《構建之法》練習題
大家經常玩成語接龍游戲,我們試一試英語的接龍吧:一個文本文件中有N 個不同的英語單詞, 我們能否寫一個程序,快速找出最長的能首尾相連的英語單詞鏈,每個單詞最多只能用一次。最長的定義是:最多單詞數量,和單詞中字母的數量無關。
例如, 文件里有:
Apple
Zoo
Elephant
Under
Fox
Dog
Moon
Leaf
Tree
Pseudopseudohypoparathyroidism
最長的相連英語單詞串為: apple - elephant – tree, 輸出到文件里面,是這樣的:
Apple
Elephant
Tree
要求程序 (WordList.exe)能處理命令行參數,知道什么是輸入文件, 輸出文件應該放在哪里。 這樣,當助教拿到學生的源程序后,就能編譯,並運行一系列的測試。
Wordlist.exe /i input1.txt /o output1.txt
Wordlist.exe /i input2.txt /o output2.txt
…
既然是測試,就會有很多邊角情況,例如,文件不存在,你的程序會崩潰么,還是能優雅地退出並給用戶提示信息?如果文件沒有任何單詞、只有一個單詞、沒有可以首尾相連的單詞,程序應該如何輸出?
程序的正確性驗證完畢后, 就可以用一些命令行計時工具來測試程序的效率。 當然,同學們也可以參考《構建之法》的介紹,自己先測試並改進程序的效率, 最好是先寫一個朴素的算法,看看用時如何,再分析效率,改進,分析...
如果輸入文件有一萬個單詞,你的程序能多快輸出結果?課程助教會在同一個電腦上用一個大文件來測試所有同學的作業,請做好准備。
補充題1: 請讓你的程序處理不同數量的單詞文件,紀錄所花費的時間(建議時間單位:毫秒)。在二維坐標系上畫出程序的效率 (x 軸:輸入文件字符數, y 軸:程序時間)。
字符數為: 10, 100, 500, 1000, 1500, 2000, 3000, 4000, 10000
補充題2:這個問題的核心算法是什么?它等價於圖論的什么問題,你的解法的效率是多少? 算法的效率和二維坐標上的曲線吻合么? 考慮到這個題目的各種特殊性,還可以繼續優化么?
補充題3:很多科班出身的同學在學校里學習的是 Java/C/C++/C# 之類的語言, 這個練習的需求就是處理一些字符串, 能否用一些處理文字比較方便的語言 (Perl, Python, JavaScript) 來做同一個題目呢? 在處理大文件的時候,這兩種語言的效率有差別么?
補充題4:能否做一個網頁版的程序,用戶可以在輸入窗口敲入各種單詞, 輸出窗口就能實時顯示最長的單詞鏈?
補充題5:上面我們提到這個題目中 “最長” 的定義是單詞數量最多, 如果我們改一下,最長 = 單詞串中所含字母最多, 那么輸入例子中的最長輸出就是:
Pseudopseudohypoparathyroidism
Moon
如果我們要求程序能處理這兩種情況(用命令行參數 /c 表示字母最多, 用命令行參數 /w 或沒有參數 表示單詞數量最多), 你的程序如何做合理的模塊化, 讓程序能有較好的可重用化,可讀性?
補充題6:上面提到的效能工具是Windows 平台的, 學生能否在別的平台運行效能測試工具,並介紹其用法?
補充題7:能否處理中文的詞組,就像成語接龍那樣,成語接龍有兩種要求,a) 接龍的兩個詞首尾的字必須是同一個字; b) 首尾的字拼音和聲調相同即可。 如何加上參數讓程序能處理中文成語接龍的情況? 如果我們是讓另外一些同學編寫中文成員接龍的模塊,那我們如何讓這個模塊被主程序調用?
從上面的各個小題目鍛煉過來,我們可以看出一個從實踐出發的構建軟件的步驟:
1. make it work 先把最主要的情況處理對,程序能跑起來
2. make it right 再把各種情況處理好
3. make it fast 優化速度
4. make it extensible 讓程序可擴展,既然能處理這個問題,我們讓它處理一些擴展問題如何?
5. make it maintainable 讓程序可讀,可維護。
這個次序也綜合了各路專家對此的看法,次序不對,就會掉進過早優化和其他一些坑里面。