Skip to content

Commit

Permalink
improve chapter 38 readability
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Jan 9, 2014
1 parent b49d7f7 commit fc03cb0
Showing 1 changed file with 21 additions and 36 deletions.
57 changes: 21 additions & 36 deletions ebook/zh/38.0.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 第三十八章:Hero在线编程判题、出题系统的演进与优化

####前言
## 前言

以前出门在外玩的时候,经常跑去网吧,去网吧也不干啥事,看看博客,改改博客,但若想修改博客上的一段代码,却发觉网吧没有装编译器这个东西,可一想到安装它需要不少时间,所以每次想在网吧写代码都作罢。

Expand All @@ -12,17 +12,13 @@

OK,本文有何问题,欢迎随时指正,对Hero有任何改进或建议,欢迎随时向我反馈,thanks。



**第三十八章、Hero在线编程判题、出题系统的演进与优化**

####一、最初的人工肉眼判题
## 一、最初的人工肉眼判题

Hero从头至尾的实现没有借用过任何开源工具,所以它的每一步探索都显得进展缓慢、推动艰难。在今年3月份之前,在Hero上玩的人不多,所以我刚来公司时,是完全人工肉眼去看每一个用户的程序思路是否正确,不确定的便得自己复制用户的代码粘贴到编译器里进行编译,看结果是否正常。也就是说如果我出一道题:求N个字符的全排列。系统后台只做一件事情,就是把用户的代码简单保存起来。

但打开许多用户的答案后,才发觉他并没有实现全排列,他只是写了一个“hello world”:

```cpp
```java
public class HelloWorld
{
public static void main(String args[])
Expand All @@ -37,16 +33,15 @@ public class HelloWorld
是的,必须得让机器实现自动判题。


## 二、写测试代码让机器自动判题

####二、写测试代码让机器自动判题
#####2.1、简单粗暴的一系列if else判断
### 2.1、简单粗暴的一系列if else判断

怎么让机器实现自动判题呢?其实原理也挺简单,可以在出题时写一段测试代码,然后用这段包含了很多组测试数据的测试代码去验证用户的程序是否正确。

比如现在有一道题是这样子的:

“最长有效括号的长度:给定只包含括号字符'('和 ')''的字符串,请找出最长的有效括号内子括号的长度。
“最长有效括号的长度:给定只包含括号字符'('和 ')'的字符串,请找出最长的有效括号内子括号的长度。

举几个例子如下:

Expand All @@ -56,7 +51,7 @@ public class HelloWorld

换言之,便是有效双括号"()"数的两倍。

给定函数原型int longestValidParentheses(string s),
给定函数原型`int longestValidParentheses(string s)`

```cpp
#include <string>
Expand All @@ -65,7 +60,7 @@ using namespace std;

class Solution
{
public:
public:
int longestValidParentheses(string s) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
Expand Down Expand Up @@ -136,13 +131,14 @@ int main()

一个for循环代替一系列if else;
不用让机器跑完所有测试数据,而是只要有一组测试数据没有通过,程序立即退出,即只要机器找到用户第一组没有通过的测试数据即可。
2.2、for循环代替if else

### 2.2、for循环代替if else

如上节所说,如果测试数据比较少量,还好说,但数据量一大,那么就得写很长很长一段的if else,那对coding的人来说显得非常业余。于是,针对下面这样一道题来看:
“合法字符串:用n个不同的字符(编号1 - n),组成一个字符串,有如下2点要求:

1、对于编号为i 的字符,如果2 * i > n,则该字符可以作为最后一个字符,但如果该字符不是作为最后一个字符的话,则该字符后面可以接任意字符;
2、对于编号为i的字符,如果2 * i <= n,则该字符不可以作为最后一个字符,且该字符后面所紧接着的下一个字符的编号一定要 >= 2 * i。
1. 对于编号为i 的字符,如果2 * i > n,则该字符可以作为最后一个字符,但如果该字符不是作为最后一个字符的话,则该字符后面可以接任意字符;
2. 对于编号为i的字符,如果2 * i <= n,则该字符不可以作为最后一个字符,且该字符后面所紧接着的下一个字符的编号一定要 >= 2 * i。

问有多少长度为M且符合条件的字符串。

Expand All @@ -152,8 +148,8 @@ int main()

函数头部

int validstring(int n,int m) {}
我们便可以写出如下的测试代码:
`int validstring(int n,int m) {}`
我们便可以写出如下的测试代码:

```cpp
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
Expand Down Expand Up @@ -208,17 +204,14 @@ int main() {

那是否可以简化写这个测试代码的工作,让系统本身变得更加智能呢?因为既然关键是测试数据的构造,那么在有了测试数据的前提下,是否只要填测试数据了,而不必再写测试代码呢?请看下面本文第3节部分。

## 三、出题系统本身的持续改进与优化


####三、出题系统本身的持续改进与优化

#####3.1、漫长的写测试代码的过程
### 3.1、漫长的写测试代码的过程

如上文所述,直到今年10月份,hero后台的判题机制一直都是,针对每一道题每一种语言单独写一份带main函数的测试代码,用这段测试代码替换掉用户程序里的main函数。如下图所示:右边的start end 代码 替换掉用户程序里的 start end 代码:

![](../images/38/38.1.jpg)


当然,这个写测试代码的过程中,得到了好友曹鹏的鼎力相助,若不是他的支持,我也坚持不了6个月,thanks。但即便有他的帮助,这个漫长的写测试代码的过程还是令人非常煎熬。

此外,推动自己一定把出题的过程简化,不想写测试代码的重要原因还有一个:即正因为自己要对每一道题每一种编程语言都写一份测试代码,导致这种出题效率异常底下,这对于整个Hero系统是十分不利的。
Expand All @@ -229,9 +222,9 @@ int main() {

这个时候,问题就来了,让自己写测试代码也就算了,虽然不轻松,但至少在曹鹏的帮助下还能应对,但怎么可以让用户也去为每一道题每一种语言写测试代码呢?然这一切只是自己的主观判断,并没有太多的实际证据支撑我的判断,于是团队决定,暂时先让社会化出题上线后再说。

#####3.2、出题时只填测试数据,不写测试代码
### 3.2、出题时只填测试数据,不写测试代码

######3.2.1、出题时一个框一个框的填测试数据
#### 3.2.1、出题时一个框一个框的填测试数据

我最担心的糟糕结果还是出现了。10月初社会化出题上线,直到10月底,尽管有一些热心的朋友在没有任何奖励的情况下来Hero上出题了,但几乎没有任何人愿意写测试代码。

Expand All @@ -241,30 +234,22 @@ int main() {

![](../images/38/38.3.jpg)

######3.2.2、出题时批量填测试数据

####3.2.2、出题时批量填测试数据
如果一道题目只有不到10组测试数据,那么出题时一个框一个框的去填测试数据是没什么问题的。但问题是,不存在某一道题的测试数据少于10组的情况,多的话几百组,甚至上千组,因此,我们很快发现必须支持批量填测试数据,于是到了今年12月底,出题系统改造成了如下图所示:

![](../images/38/38.4.jpg)

######.3.3、后续的改进、优化
####.3.3、后续的改进、优化

当然,直到现在,出题系统还有很多需要改进、优化的地方,如需支持数组,支持多行输入对应多行输出,直到最终的完全OJ模式,这些请待本文后续更新。团队还有很多事情要做,但我们一直在努力,在整个团队的推动下,Hero也一直在前进,从未退步。



**相关链接**

* Hero在线编程网站:http://hero.csdn.net/
* 本文2.1节问题的在线挑战地址:http://hero.csdn.net/Question/Details?ID=54&ExamID=52
* 本文2.2节问题的在线编程地址:http://hero.csdn.net/Question/Details?ID=74&ExamID=72


####后记

感谢大家关注本编程艺术系列,欢迎大家继续关注或贡献编程艺术[github:https://github.com/julycoding/The-Art-Of-Programming-by-July](https://github.com/julycoding/The-Art-Of-Programming-by-July),也希望各位继续支持Hero。有何问题,欢迎随时向我反馈,本文完。

July、二零一三年十二月二十八日。****
July、二零一三年十二月二十八日。

**原文链接**

Expand Down

0 comments on commit fc03cb0

Please sign in to comment.