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, 可以看到最清晰的图片)
项目分工
性能优化
该测试是生成一万条数值100内的算式, 用时437ms, 该程序耗时间大部分是生成每一条函数时调用了的随机函数
优化方案
因为randint产生最大系统耗时
全部换用random原始函数, 借用mod取模运算实现range功能, 避免 randint调用过程中的 randrange耗时, 使用X1,X2两个参数辅助优化符号的选择, 具体实现如下图
+ 优化Print 文件写入, 用一个字符串out先生成全部算式, 再一次性写入到文件
优化效果如下
设计实现过程&代码说明
Class Generate
1 class Genera:
2
3 def __init__(self, numbers, range):
4 'self.numbers 是生成题目总个数, self.range 是数值的范围'
5 self.numbers = numbers
6 self.range = range
7 self.filename = 'Exercises.txt'
8 self.Fomulas()
9
10 def GeneralOneFormula(self):
11 Range = self.range
12 # 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 = 0
22 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 = CountNUmbers
34 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) % OperateNumbers
48 rightPosition = random.randint(leftPosition + 2, OperateNumbers + 1) - 1
49 # rightPosition = int(random.random() * 10000) % OperateNumbers + 1
50 term = '(' + str(Counts[leftPosition])
51 Counts[leftPosition] = term
52 term = str(Counts[rightPosition]) + ')'
53 Counts[rightPosition] = term
54 # 合并符号list 数字括号list
55 FinalList = []
56 j = 0
57 k = 0
58 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 return FinalList
69
70 def Fomulas(self):
71 Range = self.range
72 Numbers = self.numbers
73 ' 生成多个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 class Answer:
2 '这是用于生成任何题目文件的结果到Answers.txt中的类'
3
4 def __init__(self, FileName):
5 self.file = FileName
6 self.OpenAFile()
7
8 def mul_divOperation(self, s):
9 sub_str = re.search('(\d+\.?\d*[*/]-?\d+\.?\d*)', s)
10 while sub_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 return s
20
21 def add_minusOperation(self, s):
22 s = '+' + s
23 tmp = re.findall('[+\-]\d+\.?\d*', s)
24 s = str(functools.reduce(lambda x, y: float(x) + float(y), tmp))
25 return s
26
27 def compute(self, formula):
28 formula = self.mul_divOperation(formula)
29 formula = self.add_minusOperation(formula)
30 return formula
31
32 def calc(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 while has_parenthesise:
42 sub_parenthesise = re.search('\([^()]*\)', formula) # 匹配最内层括号
43 if sub_parenthesise:
44 formula = formula.replace(sub_parenthesise.group(), self.compute(sub_parenthesise.group()[1:-1]))
45 else:
46 has_parenthesise = False
47 ret = self.compute(formula)
48 return ret
49
50 def Transfer(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): return formula[: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 - termD
63 if (termD > Deno): termD = termD - Deno
64 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 return answers
70 else:
71 return formula
72
73 def OpenAFile(self):
74 fileE = open(self.file, "r+")
75 string = fileE.read()
76 fileE.close()
77 string = string.replace('÷', '/')
78 out = ""
79 for line in string.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 class Verify:
2 '这是一个用于修正有负数结果的式子,判断式子是否有重复,以及生成题目序号的类,判断/后面有没有0'
3
4 # 筛选出等式中的符号
5 def __init__(self, FileName):
6 self.file = FileName
7 self.VerifyAFile()
8
9 def VerifyAFile(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 in lines:
15 s = l
16 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) + '. ' + l
21 w.write(l)
22 No += 1
23 r.close()
24 w.close()
25
26 def filt_sym(self, e1_fs):
27 sym_get = ""
28 for sym in e1_fs:
29 if sym == '+' or sym == '-' or sym == '*' or sym == '/':
30 sym_get = sym_get + sym
31 return sym_get
32
33 # 筛选出等式中的数字
34 def filt_num(self, e1_fn):
35 num_get = []
36 num_c = ""
37 for num in e1_fn:
38 if num != '+' and num != '-' and num != '*' and num != '/':
39 flag = 1
40 num_c += num
41 else:
42 flag = 0
43 if flag == 0:
44 num_get = num_get + [float(num_c)]
45 num_c = ""
46 num_get = num_get + [float(num_c)]
47 return num_get
48
49 # 判断优先级
50 def judge_pri(self, sym_int):
51 i = 0
52 sym_p = []
53 for sym_jp in sym_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 = 0
63 for sym_jp in sym_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 return sym_p
73
74 # 等式运算计算细节实现
75 def int_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 return float(num[0])
105
106 # 等式运算
107 def compute_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 return str(flag)
116
117 # 将等式中括号里面的等式提取出来
118 def judge_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 return False
125 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 return equ_j
128
129 def math_compute(self, equation):
130 equ_m = equation
131 while equ_m.find('(') != -1:
132 if equ_m.find('(') != -1:
133 equ_m = self.judge_bracket(equ_m)
134 if not equ_m:
135 break;
136 else:
137 break
138 if not equ_m:
139 return 0
140 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 return 0
144 else:
145 return 1
146 else:
147 return 1
Class Verify
Class Judge
Class Judge
1 class Judge:
2 '判断Exercises 和 Answers.txt ,并返回处理结果'
3
4 def __init__(self, FileName, FilenameAns):
5 self.user_file = FileName
6 self.standAns_file = FilenameAns
7 self.judge_ans(self.user_file, self.standAns_file)
8
9 def judge_ans(self, user_ans, stand_ans):
10 user_a = open(user_ans, 'r')
11 std_a = open(stand_ans, 'r')
12 i = 0
13 c_sum = []
14 e_sum = []
15 while 1:
16 equa_u = user_a.readline()
17 equa_s = std_a.readline()
18 if not equa_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 import OptionParser
2
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 and options.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 and options.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 not options.Numbers:
25 '回答-a后面的filename题目文件,并输出结果到Answers.txt文件'
26 fileA = Answer(options.AnsFile)
27
28 if options.ProExFile and options.Numbers and options.Range and not options.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 not options.ProExFile:
33 '-j 接一个用户的答案文件, 并将其和标准答案文件Answers.txt比较'
34 FileA = Judge(options.JudgeFile, "Answers.txt")
命令行传参
import re
import functools
# -*- coding: UTF-8 -*-
import random
from optparse import OptionParser usage = "[<-n> + 数字] 确定题目条数 [<-r> + 数字] 确定数字范围 \n 可选参数: \n <-u> 生成有负数出现的题目 \n [<-a> + (filename)] 回答filename文件的题目 \n [<-j> + (filename)] 批改filename文件的题目"
parser = OptionParser(usage)
parser.print_help()
parser.add_option("-n", action='store', type='int', dest='Numbers', help="生成Numbers条无负数结果的算式,输出文件是StandExercises.txt")
parser.add_option("-r", action='store', type='int', dest='Range', help="指定数字Range范围")
parser.add_option("-u", action='store', type='string', dest='ProExFile', help="生成Numbers条有负数结果的算式,输出文件时Exercises.txt")
parser.add_option("-a", action='store', type='string', dest='AnsFile', help="指定题目文件,并生成答案到Answers.txt")
parser.add_option("-j", action='store', type='string', dest='JudgeFile', help="指定用户答案文件,并将其和标准Answers.txt对比")
options, args = parser.parse_args() class Genera: def __init__(self, numbers, range):
'self.numbers 是生成题目总个数, self.range 是数值的范围'
self.numbers = numbers
self.range = range
self.filename = 'Exercises.txt'
self.Fomulas() def GeneralOneFormula(self):
Range = self.range
# OperateNumbers = random.randint(1, 3)
X1 = int(random.random() * 10000)
X2 = int(random.random() * 10000)
OperateNumbers = X1 % 3 + 1
CountNUmbers = OperateNumbers + 1
Ostyle = ['+', '-', '*', '÷'] # 生成符号list
Operates = []
a = 0
while (a <= OperateNumbers):
# Operates.append(random.choice(Ostyle))
if (a == 0):
Operates.append(Ostyle[X1 % 4])
if (a == 1):
Operates.append(Ostyle[X2 % 4])
if (a == 2):
Operates.append(Ostyle[(X1 + X2) % 4])
a += 1
# 生成数字list与括号list
Counts = []
i = CountNUmbers
while (i > 0):
X = int(random.random() * 10000) % Range + 1
if (X % 10 != 1):
term = str(X)
Counts.append(term)
else:
term = [str(X), '/', str(int(random.random() * 10000) % Range + 1)]
termT = ''.join(term)
# 此处插入分数化简
Counts.append(termT)
i -= 1
if ((Operates.count('-') != 0) and (Operates.count('+') != 0) and (
int(random.random() * 10000) % 7 == 1)): # 假定1/7的括号生成概率
leftPosition = int(random.random() * 10000) % OperateNumbers
rightPosition = random.randint(leftPosition + 2, OperateNumbers + 1) - 1
# rightPosition = int(random.random() * 10000) % OperateNumbers + 1
term = '(' + str(Counts[leftPosition])
Counts[leftPosition] = term
term = str(Counts[rightPosition]) + ')'
Counts[rightPosition] = term
# 合并符号list 数字括号list
FinalList = []
j = 0
k = 0
i = OperateNumbers + CountNUmbers - 1
while (i >= 0):
if (i % 2 != 1):
FinalList.append(Counts[j])
j += 1
else:
FinalList.append(Operates[k])
k += 1
i -= 1
FinalList = ''.join(FinalList)
return FinalList def Fomulas(self):
Range = self.range
Numbers = self.numbers
' 生成多个Formula并写入文档 '
file = open("Exercises.txt", 'a+')
out = ""
for i in range(1, Numbers + 1):
out = out + self.GeneralOneFormula() + '\n'
print(out, file=file)
file.close() class Answer:
'这是用于生成任何题目文件的结果到Answers.txt中的类' def __init__(self, FileName):
self.file = FileName
self.OpenAFile() def mul_divOperation(self, s):
sub_str = re.search('(\d+\.?\d*[*/]-?\d+\.?\d*)', s)
while sub_str:
sub_str = sub_str.group()
if sub_str.count('*'):
l_num, r_num = sub_str.split('*')
s = s.replace(sub_str, str(float(l_num) * float(r_num)))
else:
l_num, r_num = sub_str.split('/')
s = s.replace(sub_str, str(float(l_num) / float(r_num)))
sub_str = re.search('(\d+\.?\d*[*/]\d+\.?\d*)', s)
return s def add_minusOperation(self, s):
s = '+' + s
tmp = re.findall('[+\-]\d+\.?\d*', s)
s = str(functools.reduce(lambda x, y: float(x) + float(y), tmp))
return s def compute(self, formula):
formula = self.mul_divOperation(formula)
formula = self.add_minusOperation(formula)
return formula def calc(self, formula):
"""计算程序入口"""
if (formula[0] == '(' and formula[len(formula) - 1] == ')'):
formula = formula.replace('(', '')
formula = formula.replace(')', '')
formula = re.sub('[^.()/*÷\-+0-9]', "", formula) # 清除非算式符号
if (formula[1] == '.'):
formula = formula.replace(formula[0:2], '') # 计算含有题目序列号的标准算式
has_parenthesise = formula.count('(')
while has_parenthesise:
sub_parenthesise = re.search('\([^()]*\)', formula) # 匹配最内层括号
if sub_parenthesise:
formula = formula.replace(sub_parenthesise.group(), self.compute(sub_parenthesise.group()[1:-1]))
else:
has_parenthesise = False
ret = self.compute(formula)
return ret def Transfer(self, formula):
'这是一个把小数字符串转换成分数的函数'
i = formula.find('.')
if (i != -1 and formula.find('-') == -1): # 如果存在小数点,只取小数点后三位
e = float(formula[0:i + 4])
intE = int(e)
term = round(e - intE, 4) # 小数部分四舍五入
if (term == 0): return formula[:i]
termD = term * 1000
Deno = 1000
if (termD % 333 == 0): Deno = 999 # 优化小学生算术题中常出现的1/3
while (termD != Deno): # 求最大公约数以化简
if (Deno > termD): Deno = Deno - termD
if (termD > Deno): termD = termD - Deno
term = int(term * 1000 / termD)
Deno = int(1000 / termD)
if (intE != 0): answers = [str(intE), '\'', str(term), '/', str(Deno)]
if (intE == 0): answers = [str(term), '/', str(Deno)]
answers = ''.join(answers)
return answers
else:
return formula def OpenAFile(self):
fileE = open(self.file, "r+")
string = fileE.read()
fileE.close()
string = string.replace('÷', '/')
out = ""
for line in string.splitlines():
# out = out + self.compute(line) + '\n'
out = out.replace('+', '')
out = out + self.Transfer(self.calc(line)) + '\n'
fileA = open("Answers.txt", "w+")
print(out, file=fileA)
fileA.close() class Verify:
'这是一个用于修正有负数结果的式子,判断式子是否有重复,以及生成题目序号的类,判断/后面有没有0' # 筛选出等式中的符号
def __init__(self, FileName):
self.file = FileName
self.VerifyAFile() def VerifyAFile(self):
No = 1
with open(self.file) as r:
lines = r.readlines()
with open('StandExercises.txt', 'w') as w:
for l in lines:
s = l
s = s.replace('÷', '/')
if ((self.math_compute(s) == 1)):
position = re.search('\Z', l).end()
l = l.replace(l[position - 1], ' = \n')
l = str(No) + '. ' + l
w.write(l)
No += 1
r.close()
w.close() def filt_sym(self, e1_fs):
sym_get = ""
for sym in e1_fs:
if sym == '+' or sym == '-' or sym == '*' or sym == '/':
sym_get = sym_get + sym
return sym_get # 筛选出等式中的数字
def filt_num(self, e1_fn):
num_get = []
num_c = ""
for num in e1_fn:
if num != '+' and num != '-' and num != '*' and num != '/':
flag = 1
num_c += num
else:
flag = 0
if flag == 0:
num_get = num_get + [float(num_c)]
num_c = ""
num_get = num_get + [float(num_c)]
return num_get # 判断优先级
def judge_pri(self, sym_int):
i = 0
sym_p = []
for sym_jp in sym_int:
if sym_jp == '/':
sym_p += [40 + i]
i += 1
elif sym_jp == '*':
sym_p += [30 + i]
i += 1
else:
i += 1
i = 0
for sym_jp in sym_int:
if sym_jp == '-':
sym_p += [20 + i]
i += 1
elif sym_jp == '+':
sym_p += [10 + i]
i += 1
else:
i += 1
return sym_p # 等式运算计算细节实现
def int_compute(self, num_int, sym_int):
sym_p_int = self.judge_pri(sym_int)
while sym_p_int != []:
sym = int(sym_p_int[0])
if sym >= 40:
if num_int[sym - 40 + 1] == 0:
return -1
num_int[sym - 40] /= num_int[sym - 40 + 1]
num = num_int[sym - 40: sym - 40 + 1]
del num_int[sym - 40 + 1: sym - 40 + 2]
sym_int = sym_int[:sym - 40] + sym_int[sym - 40 + 1:]
elif sym >= 30:
num_int[sym - 30] *= num_int[sym - 30 + 1]
num = num_int[sym - 30: sym - 30 + 1]
del num_int[sym - 30 + 1: sym - 30 + 2]
sym_int = sym_int[:sym - 30] + sym_int[sym - 30 + 1:]
elif sym >= 20:
num_int[sym - 20] -= num_int[sym - 20 + 1]
num = num_int[sym - 20: sym - 20 + 1]
if num[0] < 0:
return -1
del num_int[sym - 20 + 1: sym - 20 + 2]
sym_int = sym_int[:sym - 20] + sym_int[sym - 20 + 1:]
elif sym >= 10:
num_int[sym - 10] += num_int[sym - 10 + 1]
num = num_int[sym - 10: sym - 10 + 1]
del num_int[sym - 10 + 1: sym - 10 + 2]
sym_int = sym_int[:sym - 10] + sym_int[sym - 10 + 1:]
sym_p_int = self.judge_pri(sym_int)
return float(num[0]) # 等式运算
def compute_c(self, e1):
num_int = float()
num_int = self.filt_num(e1)
sym_int = self.filt_sym(e1)
flag = self.int_compute(num_int, sym_int)
if flag < 0:
return 'f'
else:
return str(flag) # 将等式中括号里面的等式提取出来
def judge_bracket(self, equ_j):
left = equ_j.rfind('(')
right = equ_j.find(')', left)
e1 = equ_j[left + 1:right]
c1 = self.compute_c(e1)
if c1 == 'f':
return False
equ_j = equ_j[0:left] + str(c1) + equ_j[(left + len(c1)):]
equ_j = equ_j[0: left + len(str(c1))] + equ_j[right + 1:]
return equ_j def math_compute(self, equation):
equ_m = equation
while equ_m.find('(') != -1:
if equ_m.find('(') != -1:
equ_m = self.judge_bracket(equ_m)
if not equ_m:
break;
else:
break
if not equ_m:
return 0
elif equ_m.find('+') != -1 or equ_m.find('-') != -1 or equ_m.find('*') != -1 or equ_m.find('/') != -1:
val = self.compute_c(equ_m)
if val == 'f':
return 0
else:
return 1
else:
return 1 class Judge:
'判断Exercises 和 Answers.txt ,并返回处理结果' def __init__(self, FileName, FilenameAns):
self.user_file = FileName
self.standAns_file = FilenameAns
self.judge_ans(self.user_file, self.standAns_file) def judge_ans(self, user_ans, stand_ans):
user_a = open(user_ans, 'r')
std_a = open(stand_ans, 'r')
i = 0
c_sum = []
e_sum = []
while 1:
equa_u = user_a.readline()
equa_s = std_a.readline()
if not equa_u:
break
ind = equa_u.rfind('=')
if equa_u[ind + 1:].strip() == equa_s.strip():
i += 1
c_sum += [i]
else:
i += 1
e_sum += [i]
print("Correct: ", len(c_sum), c_sum)
print("Wrong: ", len(e_sum), e_sum) if options.Numbers and options.Range and options.ProExFile:
'生成Numbers条有负数结果的算式, 再将其标准化(去除中间过程有负数结果的算式以及/后面有0的非法算式), 输出文件是StandExercises.txt'
fileE = Genera(options.Numbers, options.Range)
fileStand = Verify(fileE.filename) if options.Numbers and options.Range and options.ProExFile and options.AnsFile:
'生成Numbers条有负数结果的算式, 再将其标准化(去除中间过程有负数结果的算式以及/后面有0的非法算式), 输出文件是StandExercises.txt'
fileE = Genera(options.Numbers, options.Range)
fileStand = Verify(fileE.filename)
fileA = Answer(options.AnsFile) if options.AnsFile and not options.Numbers:
'回答-a后面的filename题目文件,并输出结果到Answers.txt文件'
fileA = Answer(options.AnsFile) if options.ProExFile and options.Numbers and options.Range and not options.AnsFile:
'生成Numbers条有负数结果的算式, 生成文件是Exercises.txt'
fileE = Genera(options.Numbers, options.Range) if options.JudgeFile and not options.Numbers and not options.Range and not options.ProExFile:
'-j 接一个用户的答案文件, 并将其和标准答案文件Answers.txt比较'
FileA = Judge(options.JudgeFile, "Answers.txt")全部代码
测试运行:
实现判断函数是否重复思路
具体实现
def hash(self,string):
# 获取算式符数目
fuhao = re.finditer('[+\-*÷]', string)
i = -1
for match in fuhao:
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
算哈希值
#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
num = 30 # 一个数据节点
class Node(object):
def __init__(self, data):
self.data = data
self.next_node = None def set_next(self, node):
self.next_node = node def get_next(self):
return self.next_node def get_data(self):
return self.data def data_equals(self, data):
return self.data == data class HashTable(object):
def __init__(self):
self.value = [None] * num def hash(self,string):
# 获取算式符数目
fuhao = re.finditer('[+\-*÷]', string)
i = -1
for match in fuhao:
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 def insert(self, data):
# if self.search(data):
# return True i = self.hash(data)
node = Node(data)
if self.value[i] is None:
self.value[i] = node
return True
else:
head = self.value[i]
while head.get_next() is not None:
head = head.get_next()
head.set_next(node)
return True def search(self, data):
i = self.hash(data)
if self.value[i] is None:
return False
else:
head = self.value[i]
while head and not head.data_equals(data):
head = head.get_next()
if head:
return head
else:
return False def delete(self, data):
if self.search(data):
i = self.hash(data)
if self.value[i].data_equals(data):
self.value[i] = self.value[i].get_next()
else:
head = self.value[i]
while not head.get_next().data_equals(data):
head = head.get_next()
head.set_next(head.get_next().get_next())
return True
else:
return False def echo(self):
i = 0
for head in self.value:
print (str(i) + ':\t'),
if head is None:
print (None),
else:
while head is not None:
print (str(head.get_data()) + ' ->'),
head = head.get_next()
print (None),
print ('')
i += 1
print("") #
# 1. 4÷86 = 12
# 2. 63÷16÷46*56 = 23
# 3. 99+38-59 = 12
# 4. 74-50 = 23
# 5. 52+47+34+4 = 24
# 6. 49*99 = 3
# 7. 4÷20 = 4
# 8. 1/86*78 = 5 if __name__ == '__main__':
hashTable = HashTable()
hashTable.insert("4÷86 = 12")
hashTable.insert("4÷86 = 12")
hashTable.insert("2. 63÷16÷46*56 = 23")
hashTable.insert("74-50 = 23")
hashTable.insert("8. 1/86*78 = 5")
hashTable.echo()
# hashTable.delete(11)
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,最终才用他的;除了争执,还有过讨论,一开始昆乘尝试一个人写生成函数时,在两人还没开始讨论的情况下,算法考虑不周全,比如,没有生成括号。最后两个人通过一起讨论,对需求进行一步步分析,最终得到一个比较完整周全的方案。整个过程下来,让我感觉到了两个人一起结对编程的不容易,合作本来是为了更好的编程,而不合理的合作却又会使得编程更加困难复杂。讨论沟通是整个过程中最为重要的事,否则会两人极其容易产生分歧,产生分歧时沟通更是需要,不然项目将很难做下去。
总的来说这是一次太匆忙的项目:
Python实现结对编程项目的更多相关文章
- 结对编程项目总结 by:陈宏伟&刘益
结对编程项目在欢快的国庆假期中也顺利结束了.从最初拿到结对编程项目的思考,再到一步一步实现,中间经历了一个漫长的过程.在我和队友的多次协商下,最终我们还是选择使用基于python来实现这一次结对编程项 ...
- 结对编程项目报告--四则运算CORE
<!doctype html> sw_lab2.mdhtml {overflow-x: initial !important;}#write, body { height: auto; } ...
- 结对编程项目——四则运算vs版
结对编程项目--四则运算vs版 1)小伙伴信息: 学号:130201238 赵莹 博客地址:点我进入 小伙伴的博客 2)实现的功能: 实现带有用户界面的四则运算:将原只能在 ...
- 20175324王陈峤宇 2018-2019-2《Java程序设计》结对编程项目-四则运算 第一周 阶段性总结
20175324王陈峤宇 2018-2019-2<Java程序设计>结对编程项目-四则运算 第一周 阶段性总结 需求分析 这次的结对作业是要求我们利用栈来设计一个计算器. 自动生成四则运算 ...
- 结对编程项目——C语言实现WordCount Web化
结对编程项目 代码地址 201631062219,201631011410 gitee项目地址:https://gitee.com/xxlznb/pair_programming 作业地址:https ...
- 20175229许钰玮 2018-2019-2《Java程序设计》结对编程项目-四则运算 第一周 阶段性总结
20175229许钰玮 2018-2019-2<Java程序设计>结对编程项目-四则运算 第一周 阶段性总结 需求分析 自动生成四则运算题目(加.减.乘.除). 既可以用前缀算法(波兰算法 ...
- 20175311胡济栋 2018-2019-2《Java程序设计》结对编程项目-四则运算 第二周 阶段性总结
20175311胡济栋 2018-2019-2<Java程序设计>结对编程项目-四则运算 第二周 阶段性总结 需求分析 这是利用栈来设计一个计算器的第二阶段总结. 自动生成四则运算的题目( ...
- 结对编程项目总结(core2组)
结对编程项目总结(core2组) 作业---四则运算(Core 第二组) ----by 吴雪晴 PB16061514 齐天杨 PB16060706 一.项目简介 项目的任务为制作一个给(貌似是?) ...
- 结对编程项目复盘:带UI的小初高数学学习软件
实现个人项目时,由于我当时的Java GUI编程基础还比较薄弱,所以我选择通过命令行实现,并将编程开发的重点放到了算法效率上去.没能设计出用户体验更佳的UI成为了我在个人项目阶段最大的遗憾. 在这次结 ...
随机推荐
- Maven零散笔记——配置Nexus
安装&配置Nexus 解压后,应该获得如下目录结构: nexus-2.0.6是nexus服务主目录 sonatype-work是真正的仓库,同时包含了nexus的配置,如定时任务.用户配置等 ...
- Oracle中没有 if exists(...)的解决方法
http://blog.csdn.net/hollboy/article/details/7550171对于Oracle中没有 if exists(...) 的语法,目前有许多种解决方法,这里先分析常 ...
- setTimeout()基础/setInterval()基础
JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成.它们向任务队列添加定时任务.初始接触它的人都觉得好简单 ...
- 高阶函数:sorted
排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的 ...
- Windows下Tomcat+nginx配置证书实现登录页https访问
最近公司出于安全考虑,需要将登录页做成https访问,其他页面仍采用http访问,环境是Linux平台,web服务器采用Tomcat + Nginx.之前没接触过nginx,这两天网上查资料,试了好多 ...
- Java设计模式(九)责任链模式 命令模式
(十七)责任链模式 责任链模式的目的是通过给予多个对象处理请求的机会,已解除请求发送者与接受者之间的耦合关系.面对对象的开发力求对象之前保持松散耦合,确保对象各自的责任最小化.这种设计能够使得系统更加 ...
- java变参
java变参是通过数组来实现的 Object[] addAll(Object[] array1, Object... array2)和Object[] addAll(Object[] array1, ...
- c#中Monitor的使用
首先lock和Minitor有什么区别呢? 其实lock在IL代码中会被翻译成Monitor.也就是Monitor.Enter(obj)和Monitor.Exit(obj). lock(obj) { ...
- U-Boot中关于TEXT_BASE,代码重定位,链接地址相关说明
都知道U-BOOT分为两个阶段,第一阶段是(~/cpu/arm920t/start.S中)在FLASH上运行(一般情况 下),完成对硬件的初始化,包括看门狗,中断缓存等,并且负责把代码搬移到SDRAM ...
- 搭建私有Nuget仓库
使用Nexus搭建私有Nuget仓库 https://www.cnblogs.com/Erik_Xu/p/9211471.html 前言 Nuget是ASP .NET Gallery的一员,是免费.开 ...