编写python程序实现_Python实现结对编程项目

开发流程

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, 可以看到最清晰的图片)

1482615-20180930120929028-587386375.png

项目分工

1482615-20180930133030926-826051947.png

性能优化

该测试是生成一万条数值100内的算式, 用时437ms, 该程序耗时间大部分是生成每一条函数时调用了的随机函数

1482615-20180930011412482-1554641236.png

1482615-20180930012042934-526895122.png

9666895.html

优化方案

因为randint产生最大系统耗时

全部换用random原始函数, 借用mod取模运算实现range功能, 避免 randint调用过程中的 randrange耗时, 使用X1,X2两个参数辅助优化符号的选择, 具体实现如下图

1482615-20180930131337360-720522320.png

+   优化Print 文件写入, 用一个字符串out先生成全部算式, 再一次性写入到文件

1482615-20180930011525857-551094426.png

优化效果如下

9666895.html

1482615-20180930011540970-789307878.png

1482615-20180930012129247-1239653564.png

设计实现过程&代码说明

Class Generate

1482615-20180930125454712-7578514.png

1482615-20180930125630592-499972181.png

ContractedBlock.gif

ExpandedBlockStart.gif

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

1482615-20180930125745075-468123856.png

ContractedBlock.gif

ExpandedBlockStart.gif

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

1482615-20180930130105257-323459005.png

1482615-20180930130138022-1090911124.png

ContractedBlock.gif

ExpandedBlockStart.gif

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

1482615-20180930130608201-902122025.png

Class Judge

1482615-20180930130729929-1528749383.png

ContractedBlock.gif

ExpandedBlockStart.gif

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

命令行传参代码

1482615-20180930130855465-599223534.png

ContractedBlock.gif

ExpandedBlockStart.gif

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")

命令行传参

ContractedBlock.gif

ExpandedBlockStart.gif

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")

全部代码

测试运行:

1482615-20180930132559817-422715772.png

1482615-20180930134601602-2093982030.png

实现判断函数是否重复思路

1482615-20181002081658116-1388079455.png

1482615-20181002081728130-592793951.png

具体实现

ContractedBlock.gif

ExpandedBlockStart.gif

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

算哈希值

ContractedBlock.gif

ExpandedBlockStart.gif

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

1482615-20180918204731085-220722166.png

2018-09-20 22:11:29

1482615-20180920221847454-806969594.png

beng le !

2018-09-23 10:33:53

继续调整思路。已经用正则表达式对字符串进行分割运算实现了多个符号存在时候的运算优先级顺序,但是在生成输出结果的时候遇到困难,解决方法是从Exercises.txt里面依次读取每一行,并对每一行进行运算后得出一个关于结果的标准CONTEXT字符串,再把CONTEXT字符串一次性写入Answers.txt中。此种做法1.可以计算任意符合要求的.txt文件,2. 利用CONTEXT一次性写入,极大优化了程序

1482615-20180923130641585-1481811861.png

2018-09-26 23:39:33

小组讨论和分析,全部重写算式生成函数,以及重写判断负数的算法

1482615-20180926234029856-1845078613.png

2018-09-28 16:04:17

在已有功能函数的基础上全部重写。因为团队合作中各种函数传参和处理没有讨论好。并且感谢俊豪同学及时提出问题,我已经写出的函数存在很多缺漏,以及有部分函数未按题目要求编写。/哭泣

合作心得:

昆乘: 合作过程中还是有非常非常多问题, 首先因为大家有选修课, 共同编程的时间并不多,其次是软件工程项目的时间计划没有做, 前面我已经实现了生成和计算然后就丢下了, 最后两天要提交了的时候才发现原来还有很多很多功能没实现. 然后最后赶进度, 函数还有很多很多值得改善的地方都没有做好. 两人小组的时间分配实在做得太差. 没有约定好哪个函数在哪个时间要编写出来, 哪个类什么时候结合, 哪个函数如何测试和优化 都没有计划出来. 因为没有提前合作构思和安排好各个类各个函数的接口, 导致所有函数有两次重写. 很多合作 和 时间计划相关的事情值得反思. 最大的收获明确使用各个类与功能并包装函数, 花了几个小时进行了性能优化, 觉得性能优化很有意思! 虽然还有一些函数还没优化. 编程能力还需要继续提升,算法和数据结构等也要重温.

俊豪: 合作一起同做一个项目比起一个人独自做相比较来说还更累一点,然而,对于存在问题的查找也更加深入。整个过程当中,有过争执,对于分数答案的一个生成两个人有不同的想法,昆乘想用正则表达式,而我觉得才用公倍数乘以有除号存在等式,而最终,因为我的算法有很大的bug,最终才用他的;除了争执,还有过讨论,一开始昆乘尝试一个人写生成函数时,在两人还没开始讨论的情况下,算法考虑不周全,比如,没有生成括号。最后两个人通过一起讨论,对需求进行一步步分析,最终得到一个比较完整周全的方案。整个过程下来,让我感觉到了两个人一起结对编程的不容易,合作本来是为了更好的编程,而不合理的合作却又会使得编程更加困难复杂。讨论沟通是整个过程中最为重要的事,否则会两人极其容易产生分歧,产生分歧时沟通更是需要,不然项目将很难做下去。

总的来说这是一次太匆忙的项目:

1482615-20180930135311349-514174151.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值