结对编程-四则运算(挑战出题)
过去两周,大家都对四则运算有了一定概念,完成了出题、判题。
接下来我们在现有的工作基础上继续做一些挑战:只出题,不判题
描述
小明(又是小明:D)目前在一家企业从事软件开发。过年回到老家,顺便看望自己的小学恩师林老师,时光飞逝,当年走路带风的林老师已经是头发花白,就快要退休了,目前还在教数学课。小明同林老师聊天交流这些年的见闻,林老师的日常则没有大风大浪,孜孜不倦地教导学生一年又一年,但是有个烦恼:几乎每一年都会遇上几个计算能力特别好的学生,他们喜欢计算题目,而且记忆力好,还能经常发现自己做过某些题目。因此林老师在出题上可谓是伤透了脑筋,重复的工作费时费力,让小明帮想想有没有什么更好的方法。小明眼睛一亮,一拍大腿,嘿~这不正是我擅长的么!
小明说道:“我帮您写个软件,在电脑上运行就可以随机生成题目,省去您的烦恼。”
林老师皱皱眉头:“前几年上面组织过培训如何使用电脑,这主意听起来好像也不错,不过……我这里没电脑可以用啊!”
小明抬头想了几秒:“对,手机!我给您做个手机app也可以。”
林老师从口袋里掏出手机:“你看我这诺基亚3310可以吗?”
小明挠头:“这不好办呀……有了,我回家写个程序,直接在自己电脑上帮您生成1万道题目,保证不重复,应该可以用到我下次回家,那时候再帮您重新生成。”
林老师:“这主意不错。那小明同学,拜托了,你可算帮了我大忙!”
小明说干就干,开始分析需求,跟林老师沟通后,得出以下几点:
- 每次生成的题目不能有重复
-
题目去重-引用自:http://www.cnblogs.com/jiel/p/4810756.html
程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。
例如:-
23 + 45
和45 + 23
是重复的题目 -
6 * 8
和8 * 6
也是重复的题目 -
3 + (2 + 1)
和1 + 2 + 3
这两个题目是重复的 - 由于
+
是左结合的,1 + 2 + 3
等价于(1 + 2) + 3
,也就是3 + (1 + 2)
,也就是3 + (2 + 1)
- 但是
1 + 2 + 3
和3 + 2 + 1
是不重复的两道题 - 因为
1 + 2 + 3
等价于(1 + 2) + 3
,而3 + 2 + 1
等价于(3 + 2) + 1
,它们之间不能通过有限次交换变成同一个题目
-
-
- 要能指定生成题目的数量
- 要能指定题目包含的运算符数量
输入
通过命令行参数形式指定题目要求
输出
输出题目到文件,一行一个题目
输入示例
$ java ExpressionGenerator 10000 5 expressions.txt
-
ExpressionGenerator
为最终执行的类(包含main函数) - 第一个参数
10000
代表需要生成的题目数量 - 第二个参数
5
代表每个题目需包含的运算符数量(除括号以外的运算符数量) - 第三个参数
expressions.txt
代表存放生成题目的文件名
输出示例
查看 expressions.txt,部分内容如下:
...
7 - 8 * 9 / 1 + 2 - 3
4 * 5 / 6 + 7 - 8 * 9
1 / 2 + 3 - 4 * 5 / 6
7 / 8 + 9 - 1 * 2 / 3
...
特别说明
- 可执行的入口类必须为
ExpressionGenerator
,方便后续验证 - 参数顺序必须遵守以上 输入示例 说明,方便后续验证
- 输出格式必须遵守以上 输出示例 说明,方便后续验证
- 为了减小随机空间,体现出去重功能:
- 操作数为个位整数,即选择范围只能是:
1
,2
,3
,4
,5
,6
,7
,8
,9
这9个数字 - 操作符选择范围只能是:
+
,-
,*
,/
, 还有括号
- 操作数为个位整数,即选择范围只能是:
要求
- 此次作业请在http://git.oschina.net/上新建一个仓库提交代码,并且在博客中给出仓库连接(代码托管)
-
请将所有需要的参与编译的
.java
文件都放在该仓库的根目录,如:ProjectDir ├── ExpressionGenerator.java ├── ... └── Other.java
- 结对编程的两位同学须各自发表博客
- 博客需描述各环节的输出,如:
- 需求分析(描述自己对需求的理解,以及后续扩展的可能性)
- 设计思路(同时输出UML类图)
- 实现过程中的关键代码解释
- 测试方法
- 运行过程截图
- 代码托管地址
- 遇到的困难及解决方法
- 对结对的小伙伴做出评价(重点指出需要改进的地方)
- 博客内容中如需展示两人的共同成果,请进行说明
如有参考或引用的设计、实现,请进行说明
- PSP
- 实现之前先在PSP中预估时间
- 实施后各个环节实际花费多少时间也请做记录
- 表中有一项: Estimate 指的“预估”这个活动,“预估时间”也是一项任务。
- 例如:我估计自己需要花30分钟来估算出整个项目需要多少时间完成,结果我花了20分钟估算出整个项目需要6个小时完成。Estimate这一项应该在“预估耗时”填写30分钟,实际耗时填写“20”分钟。
- 一级和二级活动的包含关系:
- Planning 这个一级活动包含了1个二级活动(Estimate)
- Development 这个一级活动包含了8个二级活动
- Reporting 这个一级活动包含了3个二级活动
- 大家在记录时间的时候, 只用记录二级活动, 然后把总数加了, 就是相应的一级活动的时间
- 这个时间的长短并不会对分数有直接影响,这是为了大家自己总结。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | ||
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | ||
· Design Spec | · 生成设计文档 | ||
· Design Review | · 设计复审 (和同事审核设计文档) | ||
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | ||
· Design | · 具体设计 | ||
· Coding | · 具体编码 | ||
· Code Review | · 代码复审 | ||
· Test | · 测试(自我测试,修改代码,提交修改) | ||
Reporting | 报告 | ||
· Test Report | · 测试报告 | ||
· Size Measurement | · 计算工作量 | ||
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | ||
合计 |
打分细则
最终提交的代码将会被拉取执行,通过传入不同参数进行测试,测试包括:
- 记录程序运行耗时
- 验证最终结果的正确性(即是否有重复的题目)
- 程序得分数将根据耗时,重复率计算得出(共65分)
- 程序不符合以上定义的输入输出,即不能使用工具进行正常测试,0分
- 生成题目重复率,根据题目重复率映射至10~45分
- 生成题目耗时,根据平均耗时映射至5~20分
- 测试以下情况(详见下文 测试工具):
- 仅能完成至生成10题的,以上得分打1折
- 仅能完成至生成30题的,以上得分打2折
- 仅能完成至生成100题的,以上得分打4折
- 仅能完成至生成1000题的,以上得分打6折
- 仅能完成至生成10000题的,以上得分打8折
- 完成至20000题的,以上得分不打折
- 博客(共35分)
- 基础分(按时提交)5分
- PSP表格 5分
- 需求分析 5分
- 设计思路 5分
- 实现过程中的关键代码解释 5分
- 遇到的困难及解决方法 5分
- 对结对小伙伴做出评价 5分
-
为自己的队友打分 (在博客中说明)
- 这里有独立的100分供分配
- 例如:一人如果得70分,另一人只能得30分
- 要求不能均分(即不能每人50分)
- 打分要给出依据,依据可以有:
- 代码提交记录
- 设计文档
- 测试
- 这里有独立的100分供分配
约定
- 博客中说明代码结构,并指明如何编译(提供编译命令)
- 如果博客不说明,评分老师根据自己经验猜测执行(编译不通过的后果由自己承担)
- 以作业截止日期的线上代码版本为准
- 编译不通过 0分
- 不严格遵守题目输入输出 0分
- 运行过程有崩溃,能得分的项目得分减半
- 如遇特殊环境问题,可在成绩公布至次日凌晨截止时间内提出复查
- 复查一般仅接受处理环境差异带来的问题
- 复查原则上不对新提交的功能代码进行评分
- 结对编程、团队项目中Git代码提交不能是一个人(要看到所有人的贡献),贡献可以是代码、设计、文档和测试
参考示例
以下是一份简单的题目生成示例(生成题目没进行去重,不够随机,也无括号,需要同学们自行动手设计实现满足以上要求的程序):
import java.util.Random;
import java.io.IOException;
import java.io.FileWriter;
public class ExpressionGenerator {
public static void main(String[] args) throws IOException {
if (args.length != 3) {
System.err.println("java ExpressionGenerator <number-of-expressions> <number-of-operator> <output-file-path>");
System.exit(1);
}
int expr_num = Integer.parseInt(args[0]);
int optr_num = Integer.parseInt(args[1]);
String file_path = args[2];
String digits = "123456789";
String operators = "+-*/";
Random rnd = new Random();
StringBuffer expr = new StringBuffer();
FileWriter fw = new FileWriter(file_path);
int r1 = rnd.nextInt(100);
for (int i = 0; i < expr_num; ++i) {
expr.append(digits.charAt(++r1 % 9));
int r2 = rnd.nextInt(100);
for (int j = 0; j < optr_num; ++j) {
expr.append(' ');
expr.append(operators.charAt(++r2 % 4));
expr.append(' ');
expr.append(digits.charAt(++r1 % 9));
}
expr.append('\n');
fw.write(expr.toString());
expr.delete(0, expr.length());
}
fw.close();
}
}
执行:
> java ExpressionGenerator 10 5 1.txt
在文件 1.txt
中输出:
4 - 5 * 6 / 7 + 8 - 9
1 * 2 / 3 + 4 - 5 * 6
7 + 8 - 9 * 1 / 2 + 3
4 * 5 / 6 + 7 - 8 * 9
1 - 2 * 3 / 4 + 5 - 6
7 - 8 * 9 / 1 + 2 - 3
4 * 5 / 6 + 7 - 8 * 9
1 / 2 + 3 - 4 * 5 / 6
7 / 8 + 9 - 1 * 2 / 3
4 - 5 * 6 / 7 + 8 - 9
测试工具
功能:
- 测试:
- 生成10道1个运算符题目
- 生成30道1个运算符题目
- 生成100道1个运算符题目
- 生成1000道3个运算符题目
- 生成10000道5个运算符题目
- 生成20000道7个运算符题目
- 发现重复的题目(按上述题目要求)
- 计算程序生成题目耗时
注意:
- 输出题目中出现不在1~9范围内的数值,工具会abort退出(当前设计)
- 该工具并不完善,使用过程中可能出现报错,崩溃,行为不正确的情况,请不要尝试使用各类输入来测试该工具。如果发现问题,请及时与我联系
使用条件:
- Windows环境(在Windows10使用VS2017编译Win32,未进行版本兼容性测试)
- 须安装JDK并配置相关环境变量
- 你编写的Java程序须严格遵守以上约定
使用方法:
- 下载后,请将
exprchecker.exe
与将要执行的类ExpressionGenerator.class
放置在统一目录,如:
ProjectDir
├── ExpressionGenerator.class
├── exprchecker.exe
├── ...
└── Other.class
- 双击
exprchecker.exe
将自动执行你的类ExpressionGenerator.class
,按照以上约定的参数,执行6组测试,输出信息如下:
Executing command: "java ExpressionGenerator 10 1 10.txt" ... DONE with status: 0
Checking your result in 10.txt ... DONE
Generating report into report_10.txt ... DONE
Executing command: "java ExpressionGenerator 30 1 30.txt" ... DONE with status: 0
Checking your result in 30.txt ... DONE
Generating report into report_30.txt ... DONE
Executing command: "java ExpressionGenerator 100 1 100.txt" ... DONE with status: 0
Checking your result in 100.txt ... DONE
Generating report into report_100.txt ... DONE
Executing command: "java ExpressionGenerator 1000 3 1000.txt" ... DONE with status: 0
Checking your result in 1000.txt ... DONE
Generating report into report_1000.txt ... DONE
Executing command: "java ExpressionGenerator 10000 5 10000.txt" ... DONE with status: 0
Checking your result in 10000.txt ... DONE
Generating report into report_10000.txt ... DONE
Executing command: "java ExpressionGenerator 20000 7 20000.txt" ... DONE with status: 0
Checking your result in 20000.txt ... DONE
Generating report into report_20000.txt ... DONE
Press [Enter] to exit ...
查看 report_10.txt
:
===============================
total expressions: 10
duplicated expressions: 0
===============================
Generation cost 125 ms.
- 生成10道题目
- 没有发现重复的题目
- 生成题目耗时125毫秒
查看 report_30.txt
:
[2 + 3] @ line 12 is repeated with:
-> [2 + 3] @ line 21
[7 / 8] @ line 10 is repeated with:
-> [7 / 8] @ line 19
[9 * 1] @ line 2 is repeated with:
-> [9 * 1] @ line 29
[4 * 5] @ line 4 is repeated with:
-> [4 * 5] @ line 13
[1 + 2] @ line 7 is repeated with:
-> [1 + 2] @ line 25
[5 + 6] @ line 9 is repeated with:
-> [5 + 6] @ line 18
===============================
total expressions: 30
duplicated expressions: 6
===============================
Generation cost 133 ms.
- 生成30道题目
- 发现6道题目重复(未成功去重哦!)
- 生成题目耗时133毫秒
- 重复题目的详细信息在文件前面部分说明