首页 技术 正文
技术 2022年11月14日
0 收藏 462 点赞 3,080 浏览 22225 个字

Github (李昆乘)(陈俊豪)

开发流程

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

Python实现结对编程项目

项目分工

Python实现结对编程项目

性能优化

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

Python实现结对编程项目Python实现结对编程项目

Python实现结对编程项目

  • 优化方案

    • 因为randint产生最大系统耗时

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

    Python实现结对编程项目

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

    •   Python实现结对编程项目

优化效果如下

Python实现结对编程项目

Python实现结对编程项目Python实现结对编程项目

设计实现过程&代码说明

Class Generate

Python实现结对编程项目Python实现结对编程项目

 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

Python实现结对编程项目

 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

Python实现结对编程项目

Python实现结对编程项目

  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

Python实现结对编程项目

Class Judge

Python实现结对编程项目

 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

命令行传参代码

Python实现结对编程项目

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

全部代码

测试运行:

Python实现结对编程项目

Python实现结对编程项目

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

Python实现结对编程项目

Python实现结对编程项目

  • 具体实现

    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

Python实现结对编程项目

2018-09-20 22:11:29

Python实现结对编程项目

beng le !

2018-09-23 10:33:53

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

Python实现结对编程项目

2018-09-26 23:39:33

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

Python实现结对编程项目

2018-09-28 16:04:17

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

合作心得:

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

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

总的来说这是一次太匆忙的项目:Python实现结对编程项目

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,474
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,889
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,724
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,479
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,118
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,278