python在调用其他程序乃至其他语言的程序上是挺强大的,于是突发奇想写了这么一个东西……
#!/usr/bin/python import subprocess import os import time def compile(lang,source): if lang=='gcc': f=open('test.c','w') f.write(source) f.close() result=os.system('gcc test.c') if result!=0: fout=os.popen('gcc test.c') return 'CE'+fout.read() return 'running' elif lang=='g++': f=open('test.cpp','w') f.write(source) f.close() result=os.system('g++ test.cpp') if result!=0: fout=os.popen('g++ test.cpp') return 'CE'+fout.read() return 'running' else: f=open('test.java','w') f.write(source) f.close() result=os.system('javac test.java') if result!=0: fout=os.popen('javac test.java') return 'CE'+fout.read() return 'running' def judge(lang,std,t0): time.clock() if lang!='java': usr=os.popen('./a.out') else: usr=os.popen('java Main') t=time.clock()*1000 print t if(t>t0): return 'TLE' usr=usr.read() result=cmp(std,usr) if result==0: return 'AC' else: tmp=std.replace('n','') while tmp.find('n')>=0: tmp=tmp.replace('n','') tmp2=usr.replace('n','') while tmp2.find('n')>=0: tmp2=tmp2.replace('n','') if cmp(tmp,tmp2)==0: return 'PE' else: return 'WA' if __name__=='__main__': if compile('cpp','')=='running': print judge('cpp','asdn',1000)
看就知道是什么了,一个灰常简陋的OJ的内核。
把源代码作为字符串参数传入,另一个参数是语言。
c和cpp直接调用gcc和g++就可以了,运行都是a.out,而java因为javac编译之后的class文件会以类名命名,所以只能强制要求代码的类是Main或者什么的了,然后上poj看了一眼发现确实poj的java就是这么要求的。
可以判断出PE,只考虑换行,行末空格什么的没处理,就是大致那么个意思。
本来是想玩玩这个os.popen的,然后查文档发现已经不推荐使用了。有234代然后开发出个popen5直接叫subprocess,不过这里先继续用着popen的了。
测时间是用的time.clock,误差应该不小,如果是瞬间结束的程序时间完全没有参考价值。外部调用应该开个线程然后监视时间什么的,外部等待时间过长直接kill掉,多线程以后再研究了。
不知道怎么用py检测内部线程占用的内存,MLE看不出来。runtimeerror当然也看不见了,而且还没测试一旦真的段错误什么的会发生什么……
因为没看过正经OJ的源码尤其是内核部分的,不知道最正规的方法是怎么实现甚至用什么语言实现的。这个代码投入实际的可能性不大。不知道有没有直接不在本地建文件编译运行的方法,有的话就有点像虚拟机什么的了。而且还要考虑安全问题,屏蔽掉一些函数的使用。
记得当年vijos垮掉之后一个山东的小朋友搞了个rqnoj.cn,他做这个的时候还是初中生……我唯一欣慰的是初中我能用C写hello world,跟一些人比已经不错了…………
发表回复