LeetCode的(包括付费)题目到处都有,可是测试数据怎么找呢?我设想了一种方法,来获得每道题的测试数据。
首先,对于权限不严格的在线评测系统,比如以前常做的Timus Online Judge,它们是可以从提交的代码里访问网络的。这样很容易,只要找一个AC的程序,每次把数据都发到自己的一个收集地址即可。
然而LeetCode的程序应该是在一个限制了网络的Container里运行的。那么程序唯一能和外界交流的途径就是出现错误结果时的输出,如下。
我们可以利用Stdout来输出最多1MB的结果。此外,LeetCode评测的机制是:新建一个Solution对象,然后多次调用要测试的函数,依次传入每个数据。与其他OJ每次都创建一个新的进程相比,这让我们有了更多的发挥空间。
因此,如果要自动化这个扒数据的过程,需要做这么几件事:
获得所有题的正确代码。不难在GitHub上找到别人写好的所有题的答案,实在不行也可以去Discussion里面找。这是因为只有前面的数据答案正确,才能看到后面的数据。
修改上面说的代码,让它记录每次调用主函数时传进的参数,并且恰好在最后一个测试时给出错误答案,而且把记录的内容输出到Stdout。如果超过1MB,还要考虑分段。我想让程序来做这种修改。
自动化登录、提交代码、记录结果的操作。
作为我用python写的第一个练手用的东西,我这几天实现了这个想法。在上面的步骤里,比较难想的是第2点。我的解决方法是:
用python的正确代码,因为直接从字符串的层面上来修改比较方便,不用真的去分析程序的结构。
在代码前面插入一些全局变量:现在是第几个测试、所有测试数据的数组、分段输出时控制想要哪一段的这个常量。
从这道题目的默认代码(只给出函数签名的那种),确认要在记录哪些函数接收到的数据。因为我们用的正确代码可能自己定义了函数,而我们并不关心。
在正确代码的上述函数的开头插入一段判断:是否到了最后一个测试,等等。如果发现输出超过1MB了,还要提示另一边再做另一次提交。
用locals()获得参数列表,这样就不用担心不同题目的函数签名区别。
这样的方法当然不能理论上处理所有python程序。不过对付一般人的编程习惯还是够的。例如,对于Two sum,修改后的程序如下:
现在实现了想象中的一部分功能。在1~20题上测试,已经能扒下18道题的数据。剩下两道因为输入是链表,不能直接变成json。估计的解决方法是允许为某些特殊的题传入一个专门的记录函数。
如果有兴趣,请参见 https://github.com/CurryX/LeetCodeAPI 。期末将至,不能再摸鱼了。
领取专属 10元无门槛券
私享最新 技术干货