又蛋疼了一下……

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,跟一些人比已经不错了…………

 


已发布

分类

来自

标签:

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注