开发流程
PSP2.1
PSP2.1
Personal Software Process Stages
预估耗时(分钟)
实际耗时(分钟)
Planning
计划
60
90
· Estimate
· 估计这个任务需要多少时间
60
90
Development
开发
580
1780
· Analysis
· 需求分析 (包括学习新技术)
100
80
· Design Spec
· 生成设计文档
50
120
· Design Review
· 设计复审 (和同事审核设计文档)
50
200
· Coding Standard
· 代码规范 (为目前的开发制定合适的规范)
30
30
· Design
· 具体设计
100
300
· Coding
· 具体编码
100
350
· Code Review
· 代码复审
60
550
· Test
· 测试(自我测试,修改代码,提交修改)
120
150
Reporting
报告
60
200
· Test Report
· 测试报告
20
150
· Size Measurement
· 计算工作量
10
15
· Postmortem & Process Improvement Plan
· 事后总结, 并提出过程改进计划
30
35
合计
700
2070
需求实现 :
使用 -n 参数控制生成题目的个数
使用 -r 参数控制题目中的数值
生成的题目中计算过程不能产生负数
生成的题目中如果存在形如e1 ÷ e2的子表达式,那么其结果应是真分数
每道题目中出现的运算符个数不超过3个
程序一次运行生成的题目不能重复(正在努力中)
在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件
程序应能支持一万道题目的生成
程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计
程序概述
(因为网页排版问题,图片字体显示比较小, 可以ctrl+鼠标滚轮放大页面显示比例或者右键该图片, 在新窗口中打开该.image, 可以看到最清晰的图片)
项目分工
性能优化
该测试是生成一万条数值100内的算式, 用时437ms, 该程序耗时间大部分是生成每一条函数时调用了的随机函数
优化方案
因为randint产生最大系统耗时
全部换用random原始函数, 借用mod取模运算实现range功能, 避免 randint调用过程中的 randrange耗时, 使用X1,X2两个参数辅助优化符号的选择, 具体实现如下图
+ 优化Print 文件写入, 用一个字符串out先生成全部算式, 再一次性写入到文件
优化效果如下
设计实现过程&代码说明
Class Generate
1 classGenera:2
3 def __init__(self, numbers, range):4 'self.numbers 是生成题目总个数, self.range 是数值的范围'
5 self.numbers =numbers6 self.range =range7 self.filename = 'Exercises.txt'
8 self.Fomulas()9
10 defGeneralOneFormula(self):11 Range =self.range12 #OperateNumbers = random.randint(1, 3)
13 X1 = int(random.random() * 10000)14 X2 = int(random.random() * 10000)15 OperateNumbers = X1 % 3 + 1
16 CountNUmbers = OperateNumbers + 1
17 Ostyle = ['+', '-', '*', '÷']18
19 #生成符号list
20 Operates =[]21 a =022 while (a <=OperateNumbers):23 #Operates.append(random.choice(Ostyle))
24 if (a ==0):25 Operates.append(Ostyle[X1 % 4])26 if (a == 1):27 Operates.append(Ostyle[X2 % 4])28 if (a == 2):29 Operates.append(Ostyle[(X1 + X2) % 4])30 a += 1
31 #生成数字list与括号list
32 Counts =[]33 i =CountNUmbers34 while (i >0):35 X = int(random.random() * 10000) % Range + 1
36 if (X % 10 != 1):37 term =str(X)38 Counts.append(term)39 else:40 term = [str(X), '/', str(int(random.random() * 10000) % Range + 1)]41 termT = ''.join(term)42 #此处插入分数化简
43 Counts.append(termT)44 i -= 1
45 if ((Operates.count('-') != 0) and (Operates.count('+') != 0) and(46 int(random.random() * 10000) % 7 == 1)): #假定1/7的括号生成概率
47 leftPosition = int(random.random() * 10000) %OperateNumbers48 rightPosition = random.randint(leftPosition + 2, OperateNumbers + 1) - 1
49 #rightPosition = int(random.random() * 10000) % OperateNumbers + 1
50 term = '(' +str(Counts[leftPosition])51 Counts[leftPosition] =term52 term = str(Counts[rightPosition]) + ')'
53 Counts[rightPosition] =term54 #合并符号list 数字括号list
55 FinalList =[]56 j =057 k =058 i = OperateNumbers + CountNUmbers - 1
59 while (i >=0):60 if (i % 2 != 1):61 FinalList.append(Counts[j])62 j += 1
63 else:64 FinalList.append(Operates[k])65 k += 1
66 i -= 1
67 FinalList = ''.join(FinalList)68 returnFinalList69
70 defFomulas(self):71 Range =self.range72 Numbers =self.numbers73 '生成多个Formula并写入文档'
74 file = open("Exercises.txt", 'a+')75 out = ""
76 for i in range(1, Numbers + 1):77 out = out + self.GeneralOneFormula() + '\n'
78 print(out, file=file)79 file.close()
Class Genera
Class Answer
1 classAnswer:2 '这是用于生成任何题目文件的结果到Answers.txt中的类'
3
4 def __init__(self, FileName):5 self.file =FileName6 self.OpenAFile()7
8 defmul_divOperation(self, s):9 sub_str = re.search('(\d+\.?\d*[*/]-?\d+\.?\d*)', s)10 whilesub_str:11 sub_str =sub_str.group()12 if sub_str.count('*'):13 l_num, r_num = sub_str.split('*')14 s = s.replace(sub_str, str(float(l_num) *float(r_num)))15 else:16 l_num, r_num = sub_str.split('/')17 s = s.replace(sub_str, str(float(l_num) /float(r_num)))18 sub_str = re.search('(\d+\.?\d*[*/]\d+\.?\d*)', s)19 returns20
21 defadd_minusOperation(self, s):22 s = '+' +s23 tmp = re.findall('[+\-]\d+\.?\d*', s)24 s = str(functools.reduce(lambda x, y: float(x) +float(y), tmp))25 returns26
27 defcompute(self, formula):28 formula =self.mul_divOperation(formula)29 formula =self.add_minusOperation(formula)30 returnformula31
32 defcalc(self, formula):33 """计算程序入口"""
34 if (formula[0] == '(' and formula[len(formula) - 1] == ')'):35 formula = formula.replace('(', '')36 formula = formula.replace(')', '')37 formula = re.sub('[^.()/*÷\-+0-9]', "", formula) #清除非算式符号
38 if (formula[1] == '.'):39 formula = formula.replace(formula[0:2], '') #计算含有题目序列号的标准算式
40 has_parenthesise = formula.count('(')41 whilehas_parenthesise:42 sub_parenthesise = re.search('\([^()]*\)', formula) #匹配最内层括号
43 ifsub_parenthesise:44 formula = formula.replace(sub_parenthesise.group(), self.compute(sub_parenthesise.group()[1:-1]))45 else:46 has_parenthesise =False47 ret =self.compute(formula)48 returnret49
50 defTransfer(self, formula):51 '这是一个把小数字符串转换成分数的函数'
52 i = formula.find('.')53 if (i != -1 and formula.find('-') == -1): #如果存在小数点,只取小数点后三位
54 e = float(formula[0:i + 4])55 intE =int(e)56 term = round(e - intE, 4) #小数部分四舍五入
57 if (term == 0): returnformula[:i]58 termD = term * 1000
59 Deno = 1000
60 if (termD % 333 == 0): Deno = 999 #优化小学生算术题中常出现的1/3
61 while (termD != Deno): #求最大公约数以化简
62 if (Deno > termD): Deno = Deno -termD63 if (termD > Deno): termD = termD -Deno64 term = int(term * 1000 /termD)65 Deno = int(1000 /termD)66 if (intE != 0): answers = [str(intE), '\'', str(term), '/', str(Deno)]67 if (intE == 0): answers = [str(term), '/', str(Deno)]68 answers = ''.join(answers)69 returnanswers70 else:71 returnformula72
73 defOpenAFile(self):74 fileE = open(self.file, "r+")75 string =fileE.read()76 fileE.close()77 string = string.replace('÷', '/')78 out = ""
79 for line instring.splitlines():80 #out = out + self.compute(line) + '\n'
81 out = out.replace('+', '')82 out = out + self.Transfer(self.calc(line)) + '\n'
83 fileA = open("Answers.txt", "w+")84 print(out, file=fileA)85 fileA.close()
Class Answer
Class Verify
1 classVerify:2 '这是一个用于修正有负数结果的式子,判断式子是否有重复,以及生成题目序号的类,判断/后面有没有0'
3
4 #筛选出等式中的符号
5 def __init__(self, FileName):6 self.file =FileName7 self.VerifyAFile()8
9 defVerifyAFile(self):10 No = 1
11 with open(self.file) as r:12 lines =r.readlines()13 with open('StandExercises.txt', 'w') as w:14 for l inlines:15 s =l16 s = s.replace('÷', '/')17 if ((self.math_compute(s) == 1)):18 position = re.search('\Z', l).end()19 l = l.replace(l[position - 1], '= \n')20 l = str(No) + '.' +l21 w.write(l)22 No += 1
23 r.close()24 w.close()25
26 deffilt_sym(self, e1_fs):27 sym_get = ""
28 for sym ine1_fs:29 if sym == '+' or sym == '-' or sym == '*' or sym == '/':30 sym_get = sym_get +sym31 returnsym_get32
33 #筛选出等式中的数字
34 deffilt_num(self, e1_fn):35 num_get =[]36 num_c = ""
37 for num ine1_fn:38 if num != '+' and num != '-' and num != '*' and num != '/':39 flag = 1
40 num_c +=num41 else:42 flag =043 if flag ==0:44 num_get = num_get +[float(num_c)]45 num_c = ""
46 num_get = num_get +[float(num_c)]47 returnnum_get48
49 #判断优先级
50 defjudge_pri(self, sym_int):51 i =052 sym_p =[]53 for sym_jp insym_int:54 if sym_jp == '/':55 sym_p += [40 +i]56 i += 1
57 elif sym_jp == '*':58 sym_p += [30 +i]59 i += 1
60 else:61 i += 1
62 i =063 for sym_jp insym_int:64 if sym_jp == '-':65 sym_p += [20 +i]66 i += 1
67 elif sym_jp == '+':68 sym_p += [10 +i]69 i += 1
70 else:71 i += 1
72 returnsym_p73
74 #等式运算计算细节实现
75 defint_compute(self, num_int, sym_int):76 sym_p_int =self.judge_pri(sym_int)77 while sym_p_int !=[]:78 sym =int(sym_p_int[0])79 if sym >= 40:80 if num_int[sym - 40 + 1] ==0:81 return -1
82 num_int[sym - 40] /= num_int[sym - 40 + 1]83 num = num_int[sym - 40: sym - 40 + 1]84 del num_int[sym - 40 + 1: sym - 40 + 2]85 sym_int = sym_int[:sym - 40] + sym_int[sym - 40 + 1:]86 elif sym >= 30:87 num_int[sym - 30] *= num_int[sym - 30 + 1]88 num = num_int[sym - 30: sym - 30 + 1]89 del num_int[sym - 30 + 1: sym - 30 + 2]90 sym_int = sym_int[:sym - 30] + sym_int[sym - 30 + 1:]91 elif sym >= 20:92 num_int[sym - 20] -= num_int[sym - 20 + 1]93 num = num_int[sym - 20: sym - 20 + 1]94 if num[0] <0:95 return -1
96 del num_int[sym - 20 + 1: sym - 20 + 2]97 sym_int = sym_int[:sym - 20] + sym_int[sym - 20 + 1:]98 elif sym >= 10:99 num_int[sym - 10] += num_int[sym - 10 + 1]100 num = num_int[sym - 10: sym - 10 + 1]101 del num_int[sym - 10 + 1: sym - 10 + 2]102 sym_int = sym_int[:sym - 10] + sym_int[sym - 10 + 1:]103 sym_p_int =self.judge_pri(sym_int)104 returnfloat(num[0])105
106 #等式运算
107 defcompute_c(self, e1):108 num_int =float()109 num_int =self.filt_num(e1)110 sym_int =self.filt_sym(e1)111 flag =self.int_compute(num_int, sym_int)112 if flag <0:113 return 'f'
114 else:115 returnstr(flag)116
117 #将等式中括号里面的等式提取出来
118 defjudge_bracket(self, equ_j):119 left = equ_j.rfind('(')120 right = equ_j.find(')', left)121 e1 = equ_j[left + 1:right]122 c1 =self.compute_c(e1)123 if c1 == 'f':124 returnFalse125 equ_j = equ_j[0:left] + str(c1) + equ_j[(left +len(c1)):]126 equ_j = equ_j[0: left + len(str(c1))] + equ_j[right + 1:]127 returnequ_j128
129 defmath_compute(self, equation):130 equ_m =equation131 while equ_m.find('(') != -1:132 if equ_m.find('(') != -1:133 equ_m =self.judge_bracket(equ_m)134 if notequ_m:135 break;136 else:137 break
138 if notequ_m:139 return0140 elif equ_m.find('+') != -1 or equ_m.find('-') != -1 or equ_m.find('*') != -1 or equ_m.find('/') != -1:141 val =self.compute_c(equ_m)142 if val == 'f':143 return0144 else:145 return 1
146 else:147 return 1
Class Verify
Class Judge
Class Judge
1 classJudge:2 '判断Exercises 和 Answers.txt ,并返回处理结果'
3
4 def __init__(self, FileName, FilenameAns):5 self.user_file =FileName6 self.standAns_file =FilenameAns7 self.judge_ans(self.user_file, self.standAns_file)8
9 defjudge_ans(self, user_ans, stand_ans):10 user_a = open(user_ans, 'r')11 std_a = open(stand_ans, 'r')12 i =013 c_sum =[]14 e_sum =[]15 while 1:16 equa_u =user_a.readline()17 equa_s =std_a.readline()18 if notequa_u:19 break
20 ind = equa_u.rfind('=')21 if equa_u[ind + 1:].strip() ==equa_s.strip():22 i += 1
23 c_sum +=[i]24 else:25 i += 1
26 e_sum +=[i]27 print("Correct:", len(c_sum), c_sum)28 print("Wrong:", len(e_sum), e_sum)
Class Judge
命令行传参代码
1 from optparse importOptionParser2
3 usage = "[<-n> + 数字] 确定题目条数 [<-r> + 数字] 确定数字范围 \n 可选参数: \n <-u> 生成有负数出现的题目 \n [<-a> + (filename)] 回答filename文件的题目 \n [<-j> + (filename)] 批改filename文件的题目"
4 parser =OptionParser(usage)5 parser.print_help()6 parser.add_option("-n", action='store', type='int', dest='Numbers', help="生成Numbers条无负数结果的算式,输出文件是StandExercises.txt")7 parser.add_option("-r", action='store', type='int', dest='Range', help="指定数字Range范围")8 parser.add_option("-u", action='store', type='string', dest='ProExFile', help="生成Numbers条有负数结果的算式,输出文件时Exercises.txt")9 parser.add_option("-a", action='store', type='string', dest='AnsFile', help="指定题目文件,并生成答案到Answers.txt")10 parser.add_option("-j", action='store', type='string', dest='JudgeFile', help="指定用户答案文件,并将其和标准Answers.txt对比")11 options, args =parser.parse_args()12
13 if options.Numbers and options.Range andoptions.ProExFile:14 '生成Numbers条有负数结果的算式, 再将其标准化(去除中间过程有负数结果的算式以及/后面有0的非法算式), 输出文件是StandExercises.txt'
15 fileE =Genera(options.Numbers, options.Range)16 fileStand =Verify(fileE.filename)17
18 if options.Numbers and options.Range and options.ProExFile andoptions.AnsFile:19 '生成Numbers条有负数结果的算式, 再将其标准化(去除中间过程有负数结果的算式以及/后面有0的非法算式), 输出文件是StandExercises.txt'
20 fileE =Genera(options.Numbers, options.Range)21 fileStand =Verify(fileE.filename)22 fileA =Answer(options.AnsFile)23
24 if options.AnsFile and notoptions.Numbers:25 '回答-a后面的filename题目文件,并输出结果到Answers.txt文件'
26 fileA =Answer(options.AnsFile)27
28 if options.ProExFile and options.Numbers and options.Range and notoptions.AnsFile:29 '生成Numbers条有负数结果的算式, 生成文件是Exercises.txt'
30 fileE =Genera(options.Numbers, options.Range)31
32 if options.JudgeFile and not options.Numbers and not options.Range and notoptions.ProExFile:33 '-j 接一个用户的答案文件, 并将其和标准答案文件Answers.txt比较'
34 FileA = Judge(options.JudgeFile, "Answers.txt")
命令行传参
1 importre2 importfunctools3 #-*- coding: UTF-8 -*-
4 importrandom5 from optparse importOptionParser6
7 usage = "[<-n> + 数字] 确定题目条数 [<-r> + 数字] 确定数字范围 \n 可选参数: \n <-u> 生成有负数出现的题目 \n [<-a> + (filename)] 回答filename文件的题目 \n [<-j> + (filename)] 批改filename文件的题目"
8 parser =OptionParser(usage)9 parser.print_help()10 parser.add_option("-n", action='store', type='int', dest='Numbers', help="生成Numbers条无负数结果的算式,输出文件是StandExercises.txt")11 parser.add_option("-r", action='store', type='int', dest='Range', help="指定数字Range范围")12 parser.add_option("-u", action='store', type='string', dest='ProExFile', help="生成Numbers条有负数结果的算式,输出文件时Exercises.txt")13 parser.add_option("-a", action='store', type='string', dest='AnsFile', help="指定题目文件,并生成答案到Answers.txt")14 parser.add_option("-j", action='store', type='string', dest='JudgeFile', help="指定用户答案文件,并将其和标准Answers.txt对比")15 options, args =parser.parse_args()16
17
18 classGenera:19
20 def __init__(self, numbers, range):21 'self.numbers 是生成题目总个数, self.range 是数值的范围'
22 self.numbers =numbers23 self.range =range24 self.filename = 'Exercises.txt'
25 self.Fomulas()26
27 defGeneralOneFormula(self):28 Range =self.range29 #OperateNumbers = random.randint(1, 3)
30 X1 = int(random.random() * 10000)31 X2 = int(random.random() * 10000)32 OperateNumbers = X1 % 3 + 1
33 CountNUmbers = OperateNumbers + 1
34 Ostyle = ['+', '-', '*', '÷']35
36 #生成符号list
37 Operates =[]38 a =039 while (a <=OperateNumbers):40 #Operates.append(random.choice(Ostyle))
41 if (a ==0):42 Operates.append(Ostyle[X1 % 4])43 if (a == 1):44 Operates.append(Ostyle[X2 % 4])45 if (a == 2):46 Operates.append(Ostyle[(X1 + X2) % 4])47 a += 1
48 #生成数字list与括号list
49 Counts =[]50 i =CountNUmbers51 while (i >0):52 X = int(random.random() * 10000) % Range + 1
53 if (X % 10 != 1):54 term =str(X)55 Counts.append(term)56 else:57 term = [str(X), '/', str(int(random.random() * 10000) % Range + 1)]58 termT = ''.join(term)59 #此处插入分数化简
60 Counts.append(termT)61 i -= 1
62 if ((Operates.count('-') != 0) and (Operates.count('+') != 0) and(63 int(random.random() * 10000) % 7 == 1)): #假定1/7的括号生成概率
64 leftPosition = int(random.random() * 10000) %OperateNumbers65 rightPosition = random.randint(leftPosition + 2, OperateNumbers + 1) - 1
66 #rightPosition = int(random.random() * 10000) % OperateNumbers + 1
67 term = '(' +str(Counts[leftPosition])68 Counts[leftPosition] =term69 term = str(Counts[rightPosition]) + ')'
70 Counts[rightPosition] =term71 #合并符号list 数字括号list
72 FinalList =[]73 j =074 k =075 i = OperateNumbers + CountNUmbers - 1
76 while (i >=0):77 if (i % 2 != 1):78 FinalList.append(Counts[j])79 j += 1
80 else:81 FinalList.append(Operates[k])82 k += 1
83 i -= 1
84 FinalList = ''.join(FinalList)85 returnFinalList86
87 defFomulas(self):88 Range =self.range89 Numbers =self.numbers90 '生成多个Formula并写入文档'
91 file = open("Exercises.txt", 'a+')92 out = ""
93 for i in range(1, Numbers + 1):94 out = out + self.GeneralOneFormula() + '\n'
95 print(out, file=file)96 file.close()97
98
99 classAnswer:100 '这是用于生成任何题目文件的结果到Answers.txt中的类'
101
102 def __init__(self, FileName):103 self.file =FileName104 self.OpenAFile()105
106 defmul_divOperation(self, s):107 sub_str = re.search('(\d+\.?\d*[*/]-?\d+\.?\d*)', s)108 whilesub_str:109 sub_str =sub_str.group()110 if sub_str.count('*'):111 l_num, r_num = sub_str.split('*')112 s = s.replace(sub_str, str(float(l_num) *float(r_num)))113 else:114 l_num, r_num = sub_str.split('/')115 s = s.replace(sub_str, str(float(l_num) /float(r_num)))116 sub_str = re.search('(\d+\.?\d*[*/]\d+\.?\d*)', s)117 returns118
119 defadd_minusOperation(self, s):120 s = '+' +s121 tmp = re.findall('[+\-]\d+\.?\d*', s)122 s = str(functools.reduce(lambda x, y: float(x) +float(y), tmp))123 returns124
125 defcompute(self, formula):126 formula =self.mul_divOperation(formula)127 formula =self.add_minusOperation(formula)128 returnformula129
130 defcalc(self, formula):131 """计算程序入口"""
132 if (formula[0] == '(' and formula[len(formula) - 1] == ')'):133 formula = formula.replace('(', '')134 formula = formula.replace(')', '')135 formula = re.sub('[^.()/*÷\-+0-9]', "", formula) #清除非算式符号
136 if (formula[1] == '.'):137 formula = formula.replace(formula[0:2], '') #计算含有题目序列号的标准算式
138 has_parenthesise = formula.count('(')139 whilehas_parenthesise:140 sub_parenthesise = re.search('\([^()]*\)', formula) #匹配最内层括号
141 ifsub_parenthesise:142 formula = formula.replace(sub_parenthesise.group(), self.compute(sub_parenthesise.group()[1:-1]))143 else:144 has_parenthesise =False145 ret =self.compute(formula)146 returnret147
148 defTransfer(self, formula):149 '这是一个把小数字符串转换成分数的函数'
150 i = formula.find('.')151 if (i != -1 and formula.find('-') == -1): #如果存在小数点,只取小数点后三位
152 e = float(formula[0:i + 4])153 intE =int(e)154 term = round(e - intE, 4) #小数部分四舍五入
155 if (term == 0): returnformula[:i]156 termD = term * 1000
157 Deno = 1000
158 if (termD % 333 == 0): Deno = 999 #优化小学生算术题中常出现的1/3
159 while (termD != Deno): #求最大公约数以化简
160 if (Deno > termD): Deno = Deno -termD161 if (termD > Deno): termD = termD -Deno162 term = int(term * 1000 /termD)163 Deno = int(1000 /termD)164 if (intE != 0): answers = [str(intE), '\'', str(term), '/', str(Deno)]165 if (intE == 0): answers = [str(term), '/', str(Deno)]166 answers = ''.join(answers)167 returnanswers168 else:169 returnformula170
171 defOpenAFile(self):172 fileE = open(self.file, "r+")173 string =fileE.read()174 fileE.close()175 string = string.replace('÷', '/')176 out = ""
177 for line instring.splitlines():178 #out = out + self.compute(line) + '\n'
179 out = out.replace('+', '')180 out = out + self.Transfer(self.calc(line)) + '\n'
181 fileA = open("Answers.txt", "w+")182 print(out, file=fileA)183 fileA.close()184
185
186 classVerify:187 '这是一个用于修正有负数结果的式子,判断式子是否有重复,以及生成题目序号的类,判断/后面有没有0'
188
189 #筛选出等式中的符号
190 def __init__(self, FileName):191 self.file =FileName192 self.VerifyAFile()193
194 defVerifyAFile(self):195 No = 1
196 with open(self.file) as r:197 lines =r.readlines()198 with open('StandExercises.txt', 'w') as w:199 for l inlines:200 s =l201 s = s.replace('÷', '/')202 if ((self.math_compute(s) == 1)):203 position = re.search('\Z', l).end()204 l = l.replace(l[position - 1], '= \n')205 l = str(No) + '.' +l206 w.write(l)207 No += 1
208 r.close()209 w.close()210
211 deffilt_sym(self, e1_fs):212 sym_get = ""
213 for sym ine1_fs:214 if sym == '+' or sym == '-' or sym == '*' or sym == '/':215 sym_get = sym_get +sym216 returnsym_get217
218 #筛选出等式中的数字
219 deffilt_num(self, e1_fn):220 num_get =[]221 num_c = ""
222 for num ine1_fn:223 if num != '+' and num != '-' and num != '*' and num != '/':224 flag = 1
225 num_c +=num226 else:227 flag =0228 if flag ==0:229 num_get = num_get +[float(num_c)]230 num_c = ""
231 num_get = num_get +[float(num_c)]232 returnnum_get233
234 #判断优先级
235 defjudge_pri(self, sym_int):236 i =0237 sym_p =[]238 for sym_jp insym_int:239 if sym_jp == '/':240 sym_p += [40 +i]241 i += 1
242 elif sym_jp == '*':243 sym_p += [30 +i]244 i += 1
245 else:246 i += 1
247 i =0248 for sym_jp insym_int:249 if sym_jp == '-':250 sym_p += [20 +i]251 i += 1
252 elif sym_jp == '+':253 sym_p += [10 +i]254 i += 1
255 else:256 i += 1
257 returnsym_p258
259 #等式运算计算细节实现
260 defint_compute(self, num_int, sym_int):261 sym_p_int =self.judge_pri(sym_int)262 while sym_p_int !=[]:263 sym =int(sym_p_int[0])264 if sym >= 40:265 if num_int[sym - 40 + 1] ==0:266 return -1
267 num_int[sym - 40] /= num_int[sym - 40 + 1]268 num = num_int[sym - 40: sym - 40 + 1]269 del num_int[sym - 40 + 1: sym - 40 + 2]270 sym_int = sym_int[:sym - 40] + sym_int[sym - 40 + 1:]271 elif sym >= 30:272 num_int[sym - 30] *= num_int[sym - 30 + 1]273 num = num_int[sym - 30: sym - 30 + 1]274 del num_int[sym - 30 + 1: sym - 30 + 2]275 sym_int = sym_int[:sym - 30] + sym_int[sym - 30 + 1:]276 elif sym >= 20:277 num_int[sym - 20] -= num_int[sym - 20 + 1]278 num = num_int[sym - 20: sym - 20 + 1]279 if num[0] <0:280 return -1
281 del num_int[sym - 20 + 1: sym - 20 + 2]282 sym_int = sym_int[:sym - 20] + sym_int[sym - 20 + 1:]283 elif sym >= 10:284 num_int[sym - 10] += num_int[sym - 10 + 1]285 num = num_int[sym - 10: sym - 10 + 1]286 del num_int[sym - 10 + 1: sym - 10 + 2]287 sym_int = sym_int[:sym - 10] + sym_int[sym - 10 + 1:]288 sym_p_int =self.judge_pri(sym_int)289 returnfloat(num[0])290
291 #等式运算
292 defcompute_c(self, e1):293 num_int =float()294 num_int =self.filt_num(e1)295 sym_int =self.filt_sym(e1)296 flag =self.int_compute(num_int, sym_int)297 if flag <0:298 return 'f'
299 else:300 returnstr(flag)301
302 #将等式中括号里面的等式提取出来
303 defjudge_bracket(self, equ_j):304 left = equ_j.rfind('(')305 right = equ_j.find(')', left)306 e1 = equ_j[left + 1:right]307 c1 =self.compute_c(e1)308 if c1 == 'f':309 returnFalse310 equ_j = equ_j[0:left] + str(c1) + equ_j[(left +len(c1)):]311 equ_j = equ_j[0: left + len(str(c1))] + equ_j[right + 1:]312 returnequ_j313
314 defmath_compute(self, equation):315 equ_m =equation316 while equ_m.find('(') != -1:317 if equ_m.find('(') != -1:318 equ_m =self.judge_bracket(equ_m)319 if notequ_m:320 break;321 else:322 break
323 if notequ_m:324 return0325 elif equ_m.find('+') != -1 or equ_m.find('-') != -1 or equ_m.find('*') != -1 or equ_m.find('/') != -1:326 val =self.compute_c(equ_m)327 if val == 'f':328 return0329 else:330 return 1
331 else:332 return 1
333
334
335 classJudge:336 '判断Exercises 和 Answers.txt ,并返回处理结果'
337
338 def __init__(self, FileName, FilenameAns):339 self.user_file =FileName340 self.standAns_file =FilenameAns341 self.judge_ans(self.user_file, self.standAns_file)342
343 defjudge_ans(self, user_ans, stand_ans):344 user_a = open(user_ans, 'r')345 std_a = open(stand_ans, 'r')346 i =0347 c_sum =[]348 e_sum =[]349 while 1:350 equa_u =user_a.readline()351 equa_s =std_a.readline()352 if notequa_u:353 break
354 ind = equa_u.rfind('=')355 if equa_u[ind + 1:].strip() ==equa_s.strip():356 i += 1
357 c_sum +=[i]358 else:359 i += 1
360 e_sum +=[i]361 print("Correct:", len(c_sum), c_sum)362 print("Wrong:", len(e_sum), e_sum)363
364
365 if options.Numbers and options.Range andoptions.ProExFile:366 '生成Numbers条有负数结果的算式, 再将其标准化(去除中间过程有负数结果的算式以及/后面有0的非法算式), 输出文件是StandExercises.txt'
367 fileE =Genera(options.Numbers, options.Range)368 fileStand =Verify(fileE.filename)369
370 if options.Numbers and options.Range and options.ProExFile andoptions.AnsFile:371 '生成Numbers条有负数结果的算式, 再将其标准化(去除中间过程有负数结果的算式以及/后面有0的非法算式), 输出文件是StandExercises.txt'
372 fileE =Genera(options.Numbers, options.Range)373 fileStand =Verify(fileE.filename)374 fileA =Answer(options.AnsFile)375
376 if options.AnsFile and notoptions.Numbers:377 '回答-a后面的filename题目文件,并输出结果到Answers.txt文件'
378 fileA =Answer(options.AnsFile)379
380 if options.ProExFile and options.Numbers and options.Range and notoptions.AnsFile:381 '生成Numbers条有负数结果的算式, 生成文件是Exercises.txt'
382 fileE =Genera(options.Numbers, options.Range)383
384 if options.JudgeFile and not options.Numbers and not options.Range and notoptions.ProExFile:385 '-j 接一个用户的答案文件, 并将其和标准答案文件Answers.txt比较'
386 FileA = Judge(options.JudgeFile, "Answers.txt")
全部代码
测试运行:
实现判断函数是否重复思路
具体实现
defhash(self,string):#获取算式符数目
fuhao = re.finditer('[+\-*÷]', string)
i= -1
for match infuhao:
i= i + 1
#获取算式结果
s = string.replace(' ', '')
t= re.search('=', s).end()
s=int(s[t:])return (s % 10) + (i * 10) #s%10表示算式结果模10, i*10表示符号位, 如22则表示三个符号且算式结果个位数是2 11则表示二个符号且算式结果个位数是1
算哈希值
1 #!/usr/bin/python
2 #-*- coding: utf-8 -*-
3 importre4 num = 30
5
6
7 #一个数据节点
8 classNode(object):9 def __init__(self, data):10 self.data =data11 self.next_node =None12
13 defset_next(self, node):14 self.next_node =node15
16 defget_next(self):17 returnself.next_node18
19 defget_data(self):20 returnself.data21
22 defdata_equals(self, data):23 return self.data ==data24
25
26 classHashTable(object):27 def __init__(self):28 self.value = [None] *num29
30 defhash(self,string):31 #获取算式符数目
32 fuhao = re.finditer('[+\-*÷]', string)33 i = -1
34 for match infuhao:35 i = i + 1
36 #获取算式结果
37 s = string.replace(' ', '')38 t = re.search('=', s).end()39 s =int(s[t:])40 return (s % 10) + (i * 10) #s%10表示算式结果模10, i*10表示符号位, 如22则表示三个符号且算式结果个位数是2 11则表示二个符号且算式结果个位数是1
41
42 definsert(self, data):43 #if self.search(data):
44 #return True
45
46 i =self.hash(data)47 node =Node(data)48 if self.value[i] isNone:49 self.value[i] =node50 returnTrue51 else:52 head =self.value[i]53 while head.get_next() is notNone:54 head =head.get_next()55 head.set_next(node)56 returnTrue57
58 defsearch(self, data):59 i =self.hash(data)60 if self.value[i] isNone:61 returnFalse62 else:63 head =self.value[i]64 while head and nothead.data_equals(data):65 head =head.get_next()66 ifhead:67 returnhead68 else:69 returnFalse70
71 defdelete(self, data):72 ifself.search(data):73 i =self.hash(data)74 ifself.value[i].data_equals(data):75 self.value[i] =self.value[i].get_next()76 else:77 head =self.value[i]78 while nothead.get_next().data_equals(data):79 head =head.get_next()80 head.set_next(head.get_next().get_next())81 returnTrue82 else:83 returnFalse84
85 defecho(self):86 i =087 for head inself.value:88 print (str(i) + ':\t'),89 if head isNone:90 print(None),91 else:92 while head is notNone:93 print (str(head.get_data()) + '->'),94 head =head.get_next()95 print(None),96 print ('')97 i += 1
98 print("")99
100 #101 #1. 4÷86 = 12
102 #2. 63÷16÷46*56 = 23
103 #3. 99+38-59 = 12
104 #4. 74-50 = 23
105 #5. 52+47+34+4 = 24
106 #6. 49*99 = 3
107 #7. 4÷20 = 4
108 #8. 1/86*78 = 5
109
110
111 if __name__ == '__main__':112 hashTable =HashTable()113 hashTable.insert("4÷86 = 12")114 hashTable.insert("4÷86 = 12")115 hashTable.insert("2. 63÷16÷46*56 = 23")116 hashTable.insert("74-50 = 23")117 hashTable.insert("8. 1/86*78 = 5")118 hashTable.echo()119 #hashTable.delete(11)
120 hashTable.echo()
构建哈希表
合作编程日志
2018-09-18 20:47:12 实现生成并写入文件,相关代码上传到Github
2018-09-20 22:11:29
beng le !
2018-09-23 10:33:53
继续调整思路。已经用正则表达式对字符串进行分割运算实现了多个符号存在时候的运算优先级顺序,但是在生成输出结果的时候遇到困难,解决方法是从Exercises.txt里面依次读取每一行,并对每一行进行运算后得出一个关于结果的标准CONTEXT字符串,再把CONTEXT字符串一次性写入Answers.txt中。此种做法1.可以计算任意符合要求的.txt文件,2. 利用CONTEXT一次性写入,极大优化了程序
2018-09-26 23:39:33
小组讨论和分析,全部重写算式生成函数,以及重写判断负数的算法
2018-09-28 16:04:17
在已有功能函数的基础上全部重写。因为团队合作中各种函数传参和处理没有讨论好。并且感谢俊豪同学及时提出问题,我已经写出的函数存在很多缺漏,以及有部分函数未按题目要求编写。/哭泣
合作心得:
昆乘: 合作过程中还是有非常非常多问题, 首先因为大家有选修课, 共同编程的时间并不多,其次是软件工程项目的时间计划没有做, 前面我已经实现了生成和计算然后就丢下了, 最后两天要提交了的时候才发现原来还有很多很多功能没实现. 然后最后赶进度, 函数还有很多很多值得改善的地方都没有做好. 两人小组的时间分配实在做得太差. 没有约定好哪个函数在哪个时间要编写出来, 哪个类什么时候结合, 哪个函数如何测试和优化 都没有计划出来. 因为没有提前合作构思和安排好各个类各个函数的接口, 导致所有函数有两次重写. 很多合作 和 时间计划相关的事情值得反思. 最大的收获明确使用各个类与功能并包装函数, 花了几个小时进行了性能优化, 觉得性能优化很有意思! 虽然还有一些函数还没优化. 编程能力还需要继续提升,算法和数据结构等也要重温.
俊豪: 合作一起同做一个项目比起一个人独自做相比较来说还更累一点,然而,对于存在问题的查找也更加深入。整个过程当中,有过争执,对于分数答案的一个生成两个人有不同的想法,昆乘想用正则表达式,而我觉得才用公倍数乘以有除号存在等式,而最终,因为我的算法有很大的bug,最终才用他的;除了争执,还有过讨论,一开始昆乘尝试一个人写生成函数时,在两人还没开始讨论的情况下,算法考虑不周全,比如,没有生成括号。最后两个人通过一起讨论,对需求进行一步步分析,最终得到一个比较完整周全的方案。整个过程下来,让我感觉到了两个人一起结对编程的不容易,合作本来是为了更好的编程,而不合理的合作却又会使得编程更加困难复杂。讨论沟通是整个过程中最为重要的事,否则会两人极其容易产生分歧,产生分歧时沟通更是需要,不然项目将很难做下去。
总的来说这是一次太匆忙的项目: