结对编程-四则运算(挑战出题)

时间:2021-08-07 03:25:42

结对编程-四则运算(挑战出题)

过去两周,大家都对四则运算有了一定概念,完成了出题、判题。
接下来我们在现有的工作基础上继续做一些挑战:只出题,不判题

描述

小明(又是小明:D)目前在一家企业从事软件开发。过年回到老家,顺便看望自己的小学恩师林老师,时光飞逝,当年走路带风的林老师已经是头发花白,就快要退休了,目前还在教数学课。小明同林老师聊天交流这些年的见闻,林老师的日常则没有大风大浪,孜孜不倦地教导学生一年又一年,但是有个烦恼:几乎每一年都会遇上几个计算能力特别好的学生,他们喜欢计算题目,而且记忆力好,还能经常发现自己做过某些题目。因此林老师在出题上可谓是伤透了脑筋,重复的工作费时费力,让小明帮想想有没有什么更好的方法。小明眼睛一亮,一拍大腿,嘿~这不正是我擅长的么!

小明说道:“我帮您写个软件,在电脑上运行就可以随机生成题目,省去您的烦恼。”

林老师皱皱眉头:“前几年上面组织过培训如何使用电脑,这主意听起来好像也不错,不过……我这里没电脑可以用啊!”

小明抬头想了几秒:“对,手机!我给您做个手机app也可以。”

林老师从口袋里掏出手机:“你看我这诺基亚3310可以吗?”

小明挠头:“这不好办呀……有了,我回家写个程序,直接在自己电脑上帮您生成1万道题目,保证不重复,应该可以用到我下次回家,那时候再帮您重新生成。”

林老师:“这主意不错。那小明同学,拜托了,你可算帮了我大忙!”

小明说干就干,开始分析需求,跟林老师沟通后,得出以下几点:

  • 每次生成的题目不能有重复
    • 题目去重-引用自:http://www.cnblogs.com/jiel/p/4810756.html

      程序一次运行生成的题目不能重复,即任何两道题目不能通过有限次交换+和×左右的算术表达式变换为同一道题目。

      例如:
      • 23 + 4545 + 23 是重复的题目
      • 6 * 88 * 6 也是重复的题目
      • 3 + (2 + 1)1 + 2 + 3 这两个题目是重复的
      • 由于+是左结合的,1 + 2 + 3 等价于(1 + 2) + 3,也就是 3 + (1 + 2),也就是3 + (2 + 1)
      • 但是1 + 2 + 33 + 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分)
    • 打分要给出依据,依据可以有:
      • 代码提交记录
      • 设计文档
      • 测试

约定

  • 博客中说明代码结构,并指明如何编译(提供编译命令)
  • 如果博客不说明,评分老师根据自己经验猜测执行(编译不通过的后果由自己承担)
  • 以作业截止日期的线上代码版本为准
  • 编译不通过 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

测试工具

exprchecker.zip

功能:

  • 测试:
    • 生成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毫秒
  • 重复题目的详细信息在文件前面部分说明