軟件工程基礎(chǔ) - 四則運(yùn)算生成

四則運(yùn)算生成

項(xiàng)目Github地址:https://github.com/Shrouding-Potion/QuestGen



PSP 2.1 Personal Software Process Stages 預(yù)估耗時(shí)(小時(shí)) 實(shí)際耗時(shí)(小時(shí))
Planning 計(jì)劃
· Estimate · 估計(jì)這個(gè)任務(wù)需要多少時(shí)間 28.25 33.5
Development 開發(fā)
· Analysis · 需求分析 1 1
· Design Spec · 生成設(shè)計(jì)文檔 1 0.5
· Design Review · 設(shè)計(jì)復(fù)審 0.25 0.0
· Coding Standard · 代碼規(guī)范 2 1
· Design · 具體設(shè)計(jì) 2 4
· Coding · 具體編碼 12 14
· Code Review · 代碼復(fù)審 3 3
· Test · 測(cè)試 5 6
Reporting 報(bào)告
· Test Report · 測(cè)試報(bào)告 1 1
· Size Measurement · 計(jì)算工作量 0 0
· Postmortem & Process Improvement Plan · 事后總結(jié)芹关,提出過(guò)程改進(jìn)計(jì)劃 1 1
合計(jì) 28.25 31.5


1. 任務(wù)目標(biāo)

  • 一階段 - 要求能生成续挟、計(jì)算、支持真分?jǐn)?shù)四則運(yùn)算侥衬,同時(shí)能接受用戶輸入答案诗祸,給出總共對(duì)錯(cuò)的數(shù)量。
  • 二階段 - 要求能支持乘方運(yùn)算并且支持**和^兩種乘方表示方式轴总,支持用戶通過(guò)設(shè)置來(lái)選擇直颅。
  • 三階段 - 要求將軟件實(shí)用化,做出電腦圖形界面程序怀樟、智能手機(jī)程序功偿、網(wǎng)頁(yè)程序或者演示動(dòng)畫。

2. 思路簡(jiǎn)述

我們使用一棵二叉樹來(lái)表示一個(gè)運(yùn)算表達(dá)式往堡,如此一來(lái)械荷,隨機(jī)的生成二叉樹就能夠生成四則運(yùn)算。如下圖所示


二叉表達(dá)式樹

觀察得知虑灰,一棵二叉表達(dá)式樹有以下幾個(gè)特征:

    1. 全樹由算符節(jié)點(diǎn)數(shù)值節(jié)點(diǎn)組成
    1. 數(shù)值節(jié)點(diǎn)為葉子節(jié)點(diǎn)
    1. 由于四則運(yùn)算為雙目運(yùn)算符吨瞎,算符節(jié)點(diǎn)都擁有左、右子樹
    1. 算符節(jié)點(diǎn)數(shù) = 數(shù)值節(jié)點(diǎn)數(shù) - 1


      由此瘩缆,我生成四則運(yùn)算的思路就是许帐,生成n個(gè)數(shù)值節(jié)點(diǎn)和n-1 個(gè)算符節(jié)點(diǎn)薛匪。
    1. 兩個(gè)列表:filled[], unfilled[]分別保存已填充子樹的和未填充子樹的缝裤。
    1. 初始時(shí)岸夯,數(shù)值節(jié)點(diǎn)由于不需要子樹端考,全放入filled中沈撞;算符節(jié)點(diǎn)由于需要安裝子樹南用,都存放在unfilled中熙卡。
    1. 之后洲脂,對(duì)每個(gè)unfilled列表中的元素x斤儿,從filled列表中隨機(jī)取出2個(gè)元素作為左右子樹,再將x移動(dòng)到filled列表中恐锦。
    1. 當(dāng)unfilled為空時(shí)往果,表達(dá)式樹構(gòu)造完成。

去重

題目中有去重的要求一铅。我們的去重方法是生成表達(dá)式樹時(shí)陕贮,將表達(dá)式的左右子樹比較大小(比較輸出的字串即可)潘飘,若右樹大于左樹肮之,則交換它們(僅應(yīng)用于滿足交換律的乘法掉缺、加法)。此操作自底向下遞歸進(jìn)行戈擒,直至整棵樹有序眶明。這樣,我們就可以追本溯源筐高,將相同表達(dá)式搜囱,但異構(gòu)的樹歸為一相同的樹。

表達(dá)式樹的歸一化



解決了異構(gòu)問(wèn)題柑土,我們就使用了Python的集合set()操作犬辰,將樹轉(zhuǎn)為字符串存入。在產(chǎn)生新的樹時(shí)冰单,若是集合中已存在幌缝,就意味著重復(fù),應(yīng)當(dāng)剔除诫欠。
去重集合

求值

對(duì)表達(dá)式求值涵卵,同樣采用自底向下的方法 。由于任意算符節(jié)點(diǎn)都是對(duì)左右子樹進(jìn)行運(yùn)算荒叼,應(yīng)當(dāng)優(yōu)先求得子樹的值轿偎。計(jì)算除法時(shí),我們使用Python的Fraction類來(lái)實(shí)現(xiàn)被廓。Fraction類實(shí)現(xiàn)了分?jǐn)?shù)的四則運(yùn)算坏晦,并含有自動(dòng)約分,為我們的求值提供了極大方便

參數(shù)開關(guān)

任務(wù)要求的參數(shù)較多嫁乘,我們使用getopt庫(kù)進(jìn)行參數(shù)的識(shí)別
在shell中昆婿,使用main -h即可顯示幫助信息:

  
  Usage:
    -h, print this help, 顯示幫助
    -n, num of expressions to generate (default: 4), 生成表達(dá)式數(shù)量
    -l, num of operators in each expression (default: 4), 每個(gè)表達(dá)式的算符數(shù)
    -e, enable Exponential Operator, 允許指數(shù)算符
    -p, Exponential Operator print as '^' rather than '**', 
        指數(shù)算符輸出為 '^', 而不是'**'3
    -v, verbose output, 冗長(zhǎng)輸出 - 打印將寫入的題目和答案
    -i, interactive mode, 交互模式,允許用戶輸入答案并得到正誤統(tǒng)計(jì)

我們的命令行程序支持使用-n 設(shè)定生成表達(dá)式數(shù)量蜓斧,-l 設(shè)定算符數(shù)目仓蛆,-e開關(guān)控制是否允許指數(shù)算符,-p設(shè)置指數(shù)算符顯示為**還是^
此外挎春,不僅能夠輸出成文件看疙,還可以加上-v使結(jié)果在控制臺(tái)打印
-i 交互模式是可以用戶輸入答案,程序統(tǒng)計(jì)正誤數(shù)量

GUI

圖形界面的設(shè)計(jì)直奋,我們選用了方便快捷的PyQt5
Qt豐富的自帶控件和獨(dú)樹一幟的信號(hào)槽機(jī)制使我們方便的編寫界面邏輯
我們制作的界面如圖所示

答題界面

歷史回顧界面

在我們的GUI程序中能庆,可以設(shè)置符號(hào)數(shù)、可以判斷用戶輸入對(duì)錯(cuò)脚线、擁有倒計(jì)時(shí)搁胆,倒計(jì)時(shí)結(jié)束后不會(huì)一概而論的否決用戶的作答,而是將現(xiàn)有輸入進(jìn)行判斷對(duì)錯(cuò)。
題目歷史可以回顧曾經(jīng)出過(guò)的題目丰涉,回顧其答案以及當(dāng)時(shí)用戶是否正確作答拓巧。

3. 單元測(cè)試

我們?yōu)橹饕K的方法都進(jìn)行了單元測(cè)試。我們總計(jì)設(shè)計(jì)了20個(gè)測(cè)試用例一死,以嘗試發(fā)掘模塊中潛在的漏洞

單元測(cè)試 Green-Across-the-Board


4. 性能分析

我們使用了cProfile對(duì)命令行程序進(jìn)行了整體的性能分析
執(zhí)行使用shell命令:

python -m cProfile -s cumulative .\src\main.py -n 1000 -e -l 6 -p

這樣肛度,我們的命令行程序會(huì)生成1000個(gè)四則運(yùn)算,包含指數(shù)投慈,算符數(shù)為6承耿,指數(shù)符號(hào)為-^
運(yùn)行時(shí),cProfile會(huì)對(duì)我們的程序進(jìn)行采樣伪煤,以分析CPU資源消耗加袋。

cProfile性能分析

從結(jié)果看出,生成算法中抱既,耗時(shí)最長(zhǎng)的部分是深拷貝操作(copy.deepcopy)职烧。該操作是去重操作的不可或缺的前置操做,其本身又是Python自帶模塊防泵,難以進(jìn)一步優(yōu)化蚀之。

5. 收獲體會(huì)

這次合作項(xiàng)目,我們2人分工明確捷泞,各司其職足删,最終圓滿的完成了任務(wù)書中的全部要求。在此我的感受頗豐锁右,激動(dòng)之心情溢于言表失受。我從軟件設(shè)計(jì)開始直至單測(cè)、性能分析全程參與項(xiàng)目咏瑟,同組同學(xué)也積極完成分配到的任務(wù)拂到,不斷地優(yōu)化他的代碼,我們一起一次又一次超出了我們一開始對(duì)項(xiàng)目的預(yù)期响蕴。

在項(xiàng)目中谆焊,我學(xué)得了分工合作的基本要領(lǐng)、實(shí)踐了課堂所學(xué)的軟件設(shè)計(jì)語(yǔ)言和軟件設(shè)計(jì)方法浦夷、鞏固了Python程序設(shè)計(jì)的技能。著實(shí)為我未來(lái)的職業(yè)生涯添磚加瓦辜王,鞏固了基礎(chǔ)劈狐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市呐馆,隨后出現(xiàn)的幾起案子肥缔,更是在濱河造成了極大的恐慌,老刑警劉巖汹来,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件续膳,死亡現(xiàn)場(chǎng)離奇詭異改艇,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)坟岔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門谒兄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人社付,你說(shuō)我怎么就攤上這事承疲。” “怎么了鸥咖?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵燕鸽,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我啼辣,道長(zhǎng)啊研,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任鸥拧,我火速辦了婚禮党远,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘住涉。我一直安慰自己麸锉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布舆声。 她就那樣靜靜地躺著花沉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪媳握。 梳的紋絲不亂的頭發(fā)上碱屁,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蛾找,去河邊找鬼娩脾。 笑死,一個(gè)胖子當(dāng)著我的面吹牛打毛,可吹牛的內(nèi)容都是我干的柿赊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼幻枉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼碰声!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起熬甫,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤胰挑,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞻颂,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡豺谈,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了贡这。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茬末。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖藕坯,靈堂內(nèi)的尸體忽然破棺而出团南,到底是詐尸還是另有隱情,我是刑警寧澤炼彪,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布吐根,位于F島的核電站,受9級(jí)特大地震影響辐马,放射性物質(zhì)發(fā)生泄漏拷橘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一喜爷、第九天 我趴在偏房一處隱蔽的房頂上張望冗疮。 院中可真熱鬧,春花似錦檩帐、人聲如沸术幔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诅挑。三九已至,卻和暖如春泛源,著一層夾襖步出監(jiān)牢的瞬間拔妥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工达箍, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留没龙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓缎玫,卻偏偏與公主長(zhǎng)得像硬纤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子赃磨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349