Players: Li certificate 3117004660 3117004671 Wu Zihao
Links: https://www.cnblogs.com/amekao/p/11663853.html
One,
1. github project Address:
https://github.com/1371272989/SE_work2
2. Interface Example:
Generation mode
Marking mode
Two, PSP form
PSP2.1 |
Personal Software Process Stages |
Estimated time consuming (minutes) |
The actual time-consuming (minutes) |
Planning |
plan |
|
|
· Estimate |
• Estimate how much time this task requires |
1200 |
1200 |
Development |
Develop |
|
|
· Analysis |
· Needs analysis (including learning new technologies) |
180 |
200 |
· Design Spec |
Generate design documents |
20 |
30 |
· Design Review |
· Design Review (and his colleagues reviewed the design documents) |
30 |
60 |
· Coding Standard |
· Code specifications (development of appropriate norms for the current development) |
30 |
30 |
· Design |
· Specific design |
100 |
100 |
· Coding |
· Specific coding |
600 |
720 |
· Code Review |
· Code Review |
200 |
180 |
· Test |
· Test (self-test, modify the code, submit modifications) |
100 |
90 |
Reporting |
report |
|
|
· Test Report |
· testing report |
30 |
40 |
· Size Measurement |
· Computing workload |
10 |
10 |
· Postmortem & Process Improvement Plan |
· Hindsight, and propose process improvement plan |
10 |
10 |
total |
|
1310 |
1470 |
Third, performance analysis
Use line_profiler module testing time:
① to re-write a time.py test, modify the main function of which is not used to get argv parameters, but the assignment directly in the program inside
② plus @profiler flag in front of the module to be tested
③ using kernprof -l time.py run the program to generate reports time.py.lprof
④ using python -m line_profiler time.py.lprof view reports
Generation mode: generating 10,000 topics range from 0 to 10
Core code generation modes:
# Generation mode ques_count = 10000 max_val = 10 random_exercises(ques_count, max_val)
The core module random_exercises used when:
Total time: 5.14441 s File: time.py Function: random_exercises at line 12 Line # Hits Time Per Hit % Time Line Contents ============================================================== 12 @profile 13 def random_exercises(q_c, m_v): 14 """ 15 and the title number of the digital input range, and generating a title file answer file 16: param q_c: the number of items 17: param m_v: maximum number 18: return: to generate questions and answers document files in the directory 19 """ 20 1 1028.0 1028.0 0.0 e_open = open("Exercises.txt", "a+") 21 1 1073.0 1073.0 0.0 a_open = open("Answers.txt", "a+") 22 10001 14619.0 1.5 0.1 for i in range(0, q_c): 23 10000 7059101.0 705.9 56.3 post = question.post_order_generator(m_v) 24 10000 217674.0 21.8 1.7 tree = question.post_to_tree(post) 25 10000 178163.0 17.8 1.4 ordinary = question.tree_to_ordinary(tree, []) 26 10000 2002280.0 200.2 16.0 readable_str = question.to_readable(ordinary) 27 10000 109711.0 11.0 0.9 e_open.write(f'{i+1}、{readable_str}\n') 28 2428198.0 29 10000 242.8 19.4 years question.count_ans = (post) 30 10000 423654.0 42.4 3.4 answer = question.to_with_fraction (ans) # converted into a mixed fraction 31 10000 103062.0 10.3 0.8 a_open.write(f'{i+1}、{answer}\n') 32 1 576.0 576.0 0.0 e_open.close() 33 1 390.0 390.0 0.0 a_open.close()
Marking mode: to answer just generated 10,000 topics to be modified
Correcting mode core code:
# Correcting mode exercise_path = "Exercises.txt" answer_path = "Answers.txt" make_standard(exercise_path) check_exercise(answer_path)
Make_standard module used when:
Total time: 1.72545 s File: time.py Function: make_standard at line 35 Line # Hits Time Per Hit % Time Line Contents ============================================================== 35 @profile 36 def make_standard(e_p): 37 """ 38 According to the topic generates standard answer StandardAnswers.txt file 39: param e_p: path of the file title 40 :return: 生成StandardAnswers.txt 41 """ 42 1 9.0 9.0 0.0 try: 43 1 409.0 409.0 0.0 e_open = open(e_p, "r") 44 except FileNotFoundError: 45 print ( "can not find the file.") 46 sys.exit() 47 except: 48 print ( "Failed to open the file, please re-run the program") 49 sys.exit() 50 1 775.0 775.0 0.0 sa_open = open("StandardAnswers.txt", "a+") 51 1 10663.0 10663.0 0.3 e_lines = e_open.readlines() 52 10001 15022.0 1.5 0.4 for line in e_lines: 53 10000 28078.0 2.8 0.7 ques_num = line.split ( ",") [0] # title number 54 10000 31358.0 3.1 0.7 ques_str = line.split ( ",") [1] .rstrip ( '\ n') # remove the front and rear number newline 55 10000 894383.0 89.4 21.3 ordinary = question.to_unreadable(ques_str) 56 10000 370173.0 37.0 8.8 post = question.ordinary_to_post(ordinary) 2341848.0 57 10000 234.2 55.7 sa = question.count_ans (post) 58 10000 413446.0 41.3 9.8 standard = question.to_with_fraction(sa) 59 10000 98687.0 9.9 2.3 sa_open.write(f'{ques_num}、{standard}\n') 60 61 1 266.0 266.0 0.0 e_open.close() 62 1 673.0 673.0 0.0 sa_open.close()
Check_exercises module used when:
Total time: 0.0277891 s File: time.py Function: check_exercise at line 64 Line # Hits Time Per Hit % Time Line Contents ============================================================== 64 @profile 65 def check_exercise(a_p): 66 """ 67 standard answer to the user answers a progressive contrast, the statistics right or wrong 68: param a_p: Users answer path 69: return: to generate statistics file Grade.txt 70 """ 71 1 459.0 459.0 0.7 sa_open = open("StandardAnswers.txt", "r") 72 1 264.0 264.0 0.4 a_open = open(a_p, "r") 73 1 5,800.0 5,800.0 8.6 sa_lines sa_open.readlines = () 74 1 3.0 3.0 0.0 right = [] 75 1 1.0 1.0 0.0 wrong = [] 76 77 10001 10571.0 1.1 15.6 for sa_line in sa_lines: 78 10000 20640.0 2.1 30.5 if sa_line == a_open.readline(): 79 10000 20990.0 2.1 31.0 right.append(sa_line.split("、")[0]) 80 else: 81 wrong.append(sa_line.split("、")[0]) 82 1 94.0 94.0 0.1 sa_open.close() 83 1 32.0 32.0 0.0 a_open.close() 84 85 1 5839.0 5839.0 8.6 grade_open = open("Grade.txt", "a+") 86 1 3019.0 3019.0 4.5 grade_open.write (f 'correct {len (right)} title: {right} \ n') 87 1 24.0 24.0 0.0 grade_open.write(f'错误{len(wrong)}题:{wrong}\n')
Analysis of the specific time to see the back Part V
Fourth, the design and implementation process
Lite class diagram
question.py is a function related to mathematical operations, most students complete the certificate by the light
main.py is the main function, responsible for obtaining user input and call the question which functions carried out by sub-Hao students
Forward and reverse output program has two parts of the module
Forward output: Reverse Polish Notation list → → converted into a binary tree into a string sequence expression for people to see a list converted →
Reverse: viewed a string list → → sequence expression Reverse Polish Notation list
Reverse Polish Notation advantage is that no parenthesis, reducing the complexity of the program, depending on the arrangement sequence of operations entirely digital, and calculation can be easily achieved by a stack pop.
Generating a topic model is used random_exercises positive output module, Mr. Cheng reverse Polish notation, using count_ans function calculation is stored Answers.txt bank and then to the positive output string Exercises.txt
Title correcting mode uses make_standard module: Reverse Exercises.txt string into the reverse Polish notation, using count_ans calculation function, save to StandardAnswers.txt
check_exercises module: Progressive and Answers.txt contrast, correct it right into the list of errors on the list of stored wrong, the final output element and number of elements in each list
Fifth, the core code to explain
1. randomly generated Reverse Polish Notation
1 def post_order_generator(max_value): 2 """ 3 Reverse Polish expression generator randomly generates a reverse Polish notation 4: param max_value: int type, indicates the maximum value The list is stored in Reverse Polish Notation: 5: return 6 """ 7 ch = ('+', '-', '×', '÷') 8 char_num = random.randrange (1, 4) 9 num_num = char_num - 1 10 # suffix_list is reverse Polish notation list, insert two numbers in front of the list 11 suffix_list = [str(get_random_fraction(max_value)), str(get_random_fraction(max_value))] 12 now_num = 2 13 while char_num or num_num: 14 if now_num >= 2: 15 if char_num and random.randrange (0, 2): 16 suffix_list.append(ch[random.randrange(0, 4)]) 17 now_num = now_num - 1 18 char_num = char_num - 1 I NUM_MIN 19 Elif: 20 suffix_list.append(str(get_random_fraction(max_value))) 21 num_num num_num = - 1 22 now_num = now_num + 1 23 else: 24 suffix_list.append(ch[random.randrange(0, 4)]) 25 char_num = char_num - 1 26 now_num = now_num - 1 27 else: 28 suffix_list.append(str(get_random_fraction(max_value))) 29 now_num = now_num + 1 30 num_num num_num = - 1 31 st = ".".join(suffix_list) 32 if st in problem_set or count_ans(suffix_list) < 0: 33 suffix_list = post_order_generator(max_value) 34 return suffix_list 35 else: 36 problem_set.add(st) 37 return suffix_list
Limiting reverse Polish notation that the first two elements must be a number, a last element must be operator, the number of digits is the number of additional operator +1
This module is a first random operators there are n equations, the number of n + 1 has removed the first two numbers into the first list, and a list of the final operator, the remaining symbols and numbers are numbers n-1, the remaining position after randomly generated
In addition to generating the reverse Polish notation into a string into a set collection, due to the uniqueness of the collection, if the new generation of expression has been in the collection, then this formula to regenerate
Unfortunately, the heavy sentence 3 + 4 + 3 and 4 we did not achieve success
2. Reverse Polish transfer binary tree
1 def post_to_tree(post_list): 2 """ Reverse Polish Notation 3 is converted into an analog binary 4: param post_list: Reverse Polish Notation list 5: return: a list, a tree 6 """ 7 ch = ('+', '-', '×', '÷') 8 temp = [] 9 for v in post_list: 10 if v in ch: 11 t1, t2 = temp.pop(), temp.pop() 12 temp.append([t2, t1, v]) 13 else: 14 temp.append(v) 15 return temp[0]
Reverse Polish Notation two numbers are stored in the leaf node, operators into the root, to become a binary tree
3. The transfer binary sequence expression
1 def tree_to_ordinary(tree_list, medium_list): 2 """ 3 convert into ordinary binary expression 4: param tree_list: List binary tree 5: param medium_list: List sequence expression, mainly for the recursive call, the beginning may pass an empty list 6: return: a list of common expressions 7 """ 8 ch_val = { '+': 1, '-': 1, '×': 2, '÷': 2} # priority symbol 9 if type(tree_list[0]) == list: 10 if ch_val[tree_list[2]] > ch_val[tree_list[0][2]]: 11 medium_list.append('(') 12 medium_list = tree_to_ordinary(tree_list[0], medium_list) 13 medium_list.append(')') 14 else: 15 medium_list = tree_to_ordinary(tree_list[0], medium_list) 16 else: 17 medium_list.append(tree_list[0]) 18 medium_list.append(tree_list[2]) 19 if type(tree_list[1]) == list: 20 medium_list.append('(') 21 medium_list = tree_to_ordinary(tree_list[1], medium_list) 22 medium_list.append(')') 23 else: 24 medium_list.append(tree_list[1]) 25 return medium_list
For a binary tree traversal sequence after that Reverse Polish Notation (postfix notation), preorder is the sequence expression (usually with style)
The difficulty lies in priority than + × ÷ number - higher number, in which case the need parentheses
4. Calculate Reverse Polish Notation
1 def count_ans(post_list): 2 """ 3 Polish calculate the inverse result of this formula and determine the legality, 4 Should a negative or zero except -1 is returned, otherwise the final result 5: param post_list: List of Reverse Polish Notation 6: return: Fraction type of result 7 """ 8 ch = ('+', '-', '×', '÷') 9 stack = [] 10 for v in post_list: 11 if v in ch: 12 t1, t2 = stack.pop(), stack.pop() 13 try: 14 if v == '+': T1 = t1 + t2 15 16 elif v == '-': T1 = t2 17 - t1 18 elif v == '×': T1 = t1 * t2 19 20 else: 21 t1 = t2 / t1 22 if t1 < 0: 23 return -1 24 stack.append(t1) 25 except ZeroDivisionError: 26 return -1 27 else: 28 stack.append(Fraction(v)) 29 return stack[0]
Using reverse Polish notation calculation formula is because there are no brackets so easy to write programs,
The RPN stack to use as a list of expressions,
Ch a new neuron progenitor deposit + - x ÷ four operators, and then reverse Polish traverse the elements in the list one by one, if the element is an operator, the operator put the first two elements of the pull stack are calculated again, until the stack until no operator
Looking back at the performance analysis:
Generation modes:
1. You can see a randomly generated reverse Polish notation post_order_generator is the most time-consuming, accounting for 56% of the time, speculation is time-consuming because the random function, a formula which takes an average of five random
2. The second is to calculate the amount of time spent RPN count_ans, because each element must traverse a list of what not to see in ch Ganso inside, and do multiplication and division
3. The third time-consuming people's surprise, actually turn to be read to_readable, may be to improper fractions into mixed numbers you need to do division
Marking mode:
1. make_standard first module is a time-consuming calculation function count_ans, ditto
2. make_standard module is a time-consuming second turn into unreadable to_unreadable, as an inverse function to_readable grounds but also because of the need to multiply the common denominator integer part plus back molecule
3. check_exercises module is the most time consuming part of progressive contrast, the portion of the code is the core module, and because of the need to match the string, the string to see if the same on both sides
Sixth, the test case
Due to the particularity of the present example when program, run a test of n can generate great convenience we judge right or wrong, the following Equation 15 is generated are
Myapp.exe -n 15 -r 10
Generated Exercises.txt
1、4'1/2 - 2/5 2、3/4 × 1/2 3、2'2/3 ÷ 1/2 + 1 4、2 × 4'1/2 ÷ 1'2/5 5、2/3 - ( 1/7 - ( 0 × 1'1/7 ) ) 6、5/9 ÷ 5 7、0 × 7/9 8、2 + 1'3/4 9、1'1/5 ÷ 1 10、7/9 ÷ 1 11、1 + 1'1/2 + 4 12、0 × 0 × 7/8 13、( 5/7 + 1'1/5 ) ÷ 1/4 14、4 × 3 15、1'1/7 × ( 0 + 1/3 )
Generated answers Answers.txt
1、4'1/10 2、3/8 3、6'1/3 4、6'3/7 5、11/21 6、1/9 7、0 8、3'3/4 9、1'1/5 10、7/9 11、6'1/2 12、0 13、7'23/35 14、12 15、8/21
Of 23,571,113 deliberately into question one of the wrong answers, save as MyAnswers.txt
1、4'1/10 2、3/9 3、6'1/4 4、6'3/7 5、 6、1/9 7、5 8、3'3/4 9、1'1/5 10、7/9 11、6 12、0 13、7'23/36 14、12 15、8/21
Modify the code execution mode using the following
Myapp.exe -e Exercises.txt -a MyAnswers.txt
Generate standard answer StandardAnswers.txt exactly the same as the original Answers.txt
1、4'1/10 2、3/8 3、6'1/3 4、6'3/7 5、11/21 6、1/9 7、0 8、3'3/4 9、1'1/5 10、7/9 11、6'1/2 12、0 13、7'23/35 14、12 15、8/21
The results also determine the correct marking Grade.txt
9 correctly Title: [ '1', '4', '6', '8', '9', '10', '12', '14', '15'] Error question 6: [ '2', '3', '5', '7', '11', '13']
VII Summary
After several days of efforts, this pair programming project perfect ending, in this twinning project, the benefits greatly.
Hao son has done in the studio inside the project, had the experience of cooperation, and the use of python experienced, and I was a school ACM training team, to design algorithms to achieve more familiar. So I am primarily responsible for generating about expressions, conversion between the calculated and fractional conversion function as well as function, while the sub-Hao is responsible for integrating the function I wrote for the performance of input and output as well as programs written analysis.
Because I was to participate in ACM contest, usually knock variable names can write more on how short is short, so this time writing code, they also weird, so the first time to the time of his son Hao difficult to understand, then Hao son came to tell me the specification python code, and taught a few tricks I use pycharm, I like a lot changed after completion. This could just as George Bernard Shaw put it, "you have an apple and I have an apple and we exchange about, only one person or an apple; you have a thought, I have an idea, we swap, a person will have two ideas . "
This time, there are many shortcomings, such as expression repeat the same question I just ruled out the postfix expression cases only, there is no final function encapsulated inside the class.