1. 程式人生 > 實用技巧 >NC20047 [HNOI2006]公路修建問題

NC20047 [HNOI2006]公路修建問題

此作業的要求參見[https://edu.cnblogs.com/campus/nenu/2020Fall/homework/11245]

版本控制

coding:https://e.coding.net/qqq2/f4/f4.git

要求1 參考《構建之法》第4章兩人合作,結對程式設計上述功能,要求每人釋出隨筆1篇 (程式碼是共同完成的,隨筆有以下兩種方式:(①允許兩人寫一份,得一份分數,二人均分;②如果每人寫一份,內容不得抄襲,體會需要是自己的,分別得到自己部落格的分數)。

(1) 給出每個功能的重點、難點、程式設計收穫。

結對夥伴:謝文強、杜蕾

功能1. 四則運算

瀏覽了四個功能,我們將功能一、二合併。隨機數以及括號的處理。

重點:處理隨機數

難點:資料的儲存的方式。由於只出四個數字的題目,我們採用二叉樹的方式。操作符有三個,可以列出了五種完全二叉樹的組合,隨機選出一棵樹,且葉子結點都為運算元。並且樹的後序遍歷為逆波蘭表示式,中序遍歷為中綴表示式。

程式設計收穫:沒有想到可以用二叉樹的方式。

重要程式碼:

 1 def init_tree(root: Node) -> None:
 2     if root.left == None and root.right == None:
 3         root.data = Fraction(random.randint(0, 9), 1)  # random.randint(1, 9)
4 else: 5 root.data = ops[random.randint(0, len(ops) - 1)] 6 init_tree(root.left) 7 init_tree(root.right) 8 9 10 def tree_lrn(root: Node) -> None: 11 if root == None: 12 return list() 13 14 nodes_left = tree_lrn(root.left) 15 nodes_right = tree_lrn(root.right)
16 return nodes_left + nodes_right + [root.data]

功能2. 支援括號

重點:括號的處理。

難點:括號的處理耗費了很多時間,我們先將括號放一對數字之間,再將不需要存在的括號進行刪除。難在括號需要去掉的地方,開始認為同優先順序的符號可以去掉,忽略了減法和除法的特性,多次確認結果,重新思考進行修改。

程式設計收穫:收穫在於一開始的思考要仔細,由於粗心大意導致部分題目結果不對,又消耗一些時間。

重要程式碼:

 1 def tree_lnr(root: Node) -> None:
 2     if root == None:
 3         return [], None
 4     elif root.left == None and root.right == None:
 5         return [root.data], None
 6 
 7     nodes_left, op_left = tree_lnr(root.left)
 8     nodes_right, op_right = tree_lnr(root.right)
 9 
10     if op_left != None and ops_level[root.data.__name__] > ops_level[op_left.__name__]:
11         nodes_left = [LeftBracket()] + nodes_left + [RightBrackt()]
12 
13     if (
14         op_right != None
15         and ops_level[root.data.__name__] > ops_level[op_right.__name__]
16     ):
17         nodes_right = [LeftBracket()] + nodes_right + [RightBrackt()]
18 
19     if (
20         op_right != None
21         and ops_level[root.data.__name__] == ops_level[op_right.__name__]
22         and (root.data.__name__ == "sub" or root.data.__name__ == "truediv")
23     ):
24         nodes_right = [LeftBracket()] + nodes_right + [RightBrackt()]
25 
26     return nodes_left + [root.data] + nodes_right, root.data

功能一和二執行截圖:

  

功能3. 限定題目數量,"精美"列印輸出,避免重複

重點:輸出對齊。

難點:python輸出的格式,找了幾篇部落格才得到想要的輸出格式。https://www.cnblogs.com/zhz-8919/p/9767357.html

程式設計收穫:遇到不會的就去找,卡著解決不了問題。

重要程式碼:

 1 if not str(args.c).isnumeric():
 2     print("題目數量必須是 正整數。")
 3     sys.exit(0)
 4 
 5 tplt = "{0:{3}^10}\t{1:{3}^10}"
 6 num = int(args.c)
 7 
 8 all_count = 0
 9 ques_list = []
10 f = open("question.txt", "w+")
11 while all_count < num:
12     try:
13         tree = copy.deepcopy(trees[random.randint(0, len(trees) - 1)])
14         init_tree(tree)
15         lrn = tree_lrn(tree)
16         lnr, op = tree_lnr(tree)
17         ans = calc_list(lrn)
18         if ans in ques_list:
19             continue
20 
21         ques_list.append(ans)
22         string = list2string(lnr) + " = "
23         string = format(string, " <30")
24 
25         question_str = f"{string}{mixed_number(ans)}\n"
26         print(question_str, end="")
27         all_count = all_count + 1
28         if f != None:
29             f.write(question_str)
30     except Exception as ex:
31         continue
32 f.close()

功能4. 支援分數出題和運算

重點:分數的處理,本次程式設計使用的是python,python自帶fractions模組。我們使用的是Fraction()這個方法。

難點:分數的結果會以小數點的形式輸出。然後對於結果的處理是使用帶分數,我們開始想對結果大於1的數進行處理,但忽略了負數,又將結果處理成絕對值的形式。執行的時候發現結果中存在2.0整數的情況,又重新將結果分成了兩種情況,即整數或分數進行處理。

程式設計收穫:還是需要仔細,培養邏輯思維。

重要程式碼:

 1 def mixed_number(frac: Fraction) -> str:
 2     string = f"{frac}"
 3     if abs(frac) > 1:
 4         mixed = frac.numerator // frac.denominator
 5 
 6         if frac - mixed == 0:
 7             string = f"{frac}"
 8         else:
 9             string = f"{mixed} {frac - mixed}"
10 
11     return string

功能三和功能四執行截圖:

  

(2)給出結對程式設計的體會

隊友很厲害,在程式設計前沒有直接上手,而是把所有問題功能綜合一起看,整理思路,一步一步找到解決辦法。所以我們用了一整快的時間都在做需求分析以及溝通、討論,這就直接使我們後面程式設計的進展的十分順利,思路也非常的明確,知道每一步都是做什麼。這是我所需要學習的地方。遇到的問題就可以討論,以前我的思路是做出一點然後再想下一步,也總會常常一個地方卡的太久,導致進展總是不順利。這次的合作非常順利,通過這次程式設計的合作,我發現兩個人的合作效率也可以很高,並且同時可以學習隊友身上的有點,以後對方的思考方式,很多時候可以讓我們跳出自己的固有思維,呈現出1+1>2的效果。

(3) 至少5項在編碼、爭論、複審等活動中花費時間較長,給你較大收穫的事件。 (10分)

  1. 前期思路的整理。一開始我自己認為會使用到棧,但是經過隊友的提示、畫圖,最終確定使用二叉樹存放數和操作符。
  2. 語言的選擇。一開始準備用java寫,但是基於之前我自己使用java過程出現一點困難,嘗試花費一些時間試圖解決,未果,遂放棄java。並且python的使用會方便許多,決定使用python,但期間多次還保留c的思維,還好隊友多次耐心講解。
  3. 括號的處理。括號是本程式容易出錯的地方,也是我認為比較難的點。有幾次以為程式設計結束,但是有括號的地方或多或少出現了一些問題,邏輯有漏洞,前期還是要需要思考的仔細一些。
  4. 較大收穫是認識到前期需求分析的重要性,把問題劃分幾個點,這樣才清楚每一步都需要做什麼。慢慢來比較快。
  5. 程式碼規範。一些細節的規範可以通過工具實現。

要求2 給出結對開發的截圖證據,要求截圖能夠證明你們是在結對程式設計。 (5分)

無人幫忙拍攝。

要求3 使用coding.net做版本控制。checkin 前要求清理 臨時檔案、可執行程式,通常執行 build-clean可以達到效果。(25分)

版本控制

coding:https://e.coding.net/qqq2/f4/f4.git

PSP: