1
1
#!/usr/bin/env python3
2
2
3
3
"""
4
- This program is free software: you can redistribute it and/or modify
5
- it under the terms of the GNU General Public License as published by
6
- the Free Software Foundation, either version 3 of the License, or
7
- (at your option) any later version.
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
8
9
- This program is distributed in the hope that it will be useful,
10
- but WITHOUT ANY WARRANTY; without even the implied warranty of
11
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
- GNU General Public License for more details.
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
13
14
- You should have received a copy of the GNU General Public License
15
- along with this program. If not, see <http://www.gnu.org/licenses/>.
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
"""
17
17
18
18
import argparse
@@ -40,7 +40,54 @@ class Verdict(Enum):
40
40
RE = 1 << 4
41
41
WA = 1 << 5
42
42
43
- def judge_case (file_i ,file_o ,cpu_limit ,mem_limit ,executable ,out_limit = None ):
43
+ def iswhite (ch ):
44
+ return chr (ch ) in [' ' , '\t ' , '\v ' , '\f ' , '\n ' , '\r ' ]
45
+
46
+ def isline (ch ):
47
+ return chr (ch ) in ['\n ' , '\r ' ]
48
+
49
+ def identical (judge , process ):
50
+ return judge == process
51
+
52
+ def standard (judge , process ):
53
+ try :
54
+ #Use a C subprogram instead python for speed increase
55
+ from _checker import standard as c_standard
56
+ return c_standard (judge , process )
57
+ except ImportError :
58
+ j = 0
59
+ p = 0
60
+ jlen = len (judge )
61
+ plen = len (process )
62
+ while j < jlen and iswhite (judge [j ]):
63
+ j += 1
64
+ while p < plen and iswhite (process [p ]):
65
+ p += 1
66
+ while True :
67
+ nj = False
68
+ np = False
69
+ while j < jlen and iswhite (judge [j ]):
70
+ nj |= isline (judge [j ])
71
+ j += 1
72
+ while p < plen and iswhite (process [p ]):
73
+ np |= isline (process [p ])
74
+ p += 1
75
+ if j == jlen or p == plen :
76
+ return j == jlen and p == plen
77
+ if nj != np :
78
+ return False
79
+ while j < jlen and not iswhite (judge [j ]):
80
+ if p >= plen :
81
+ return False
82
+ if judge [j ] != process [p ]:
83
+ return False
84
+ j += 1
85
+ p += 1
86
+
87
+ def check (judge_output , process_output , checker = standard ):
88
+ return checker (judge_output , process_output )
89
+
90
+ def judge_case (file_i ,file_o ,cpu_limit ,mem_limit ,executable ,checker , out_limit = None ):
44
91
r ,w = os .pipe ()
45
92
os .set_inheritable (w ,True )
46
93
os .set_inheritable (2 ,True )
@@ -77,19 +124,24 @@ def judge_case(file_i,file_o,cpu_limit,mem_limit,executable,out_limit=None):
77
124
if os .WEXITSTATUS (return_status ) != 0 :
78
125
return Verdict .RE ,rusage .ru_utime ,rusage .ru_maxrss ,return_status
79
126
answer = open (file_o ,"rb" ).read ()
80
- if answer != result :
127
+ if not check ( answer , result , checker ) :
81
128
return Verdict .WA ,rusage .ru_utime ,rusage .ru_maxrss ,return_status
82
129
return Verdict .AC ,rusage .ru_utime ,rusage .ru_maxrss ,return_status
83
130
84
131
def main ():
132
+ checkers = {
133
+ 'standard' : standard ,
134
+ 'identical' : identical ,
135
+ }
85
136
parser = argparse .ArgumentParser (description = "An offline judging tool." )
86
137
parser .add_argument ("test_cases" , help = "Directory that contains the test cases to judge with." )
87
138
parser .add_argument ("cpu_limit" , type = float , help = "Time limit." )
88
139
parser .add_argument ("mem_limit" , help = "Memory limit." )
89
140
parser .add_argument ("executable" , help = "File to run." )
141
+ parser .add_argument ("checker" , default = "standard" , nargs = "?" , choices = checkers .keys (), help = "Checker to be used to compare outputs." )
90
142
args = parser .parse_args ()
91
143
MEMORY_UNIT = {
92
- "B" : 2 ** 0 ,
144
+ "B" : 2 ** 0 ,
93
145
"K" : 2 ** 10 ,
94
146
"M" : 2 ** 20 ,
95
147
"G" : 2 ** 30 ,
@@ -104,6 +156,7 @@ def main():
104
156
cpu_limit = args .cpu_limit
105
157
mem_limit = (int (args .mem_limit [:- 1 ]) * MEMORY_UNIT [args .mem_limit [- 1 :]]) & - mmap .PAGESIZE
106
158
executable = args .executable
159
+ checker = checkers [args .checker ]
107
160
num_ac = 0
108
161
status_mask = 0
109
162
cpu_total = 0.0
@@ -118,7 +171,7 @@ def main():
118
171
recursive_judge (os .path .join (case ,filename ),depth + 1 )
119
172
elif case .endswith (".in" ) and os .path .isfile (case ) and os .path .isfile (case [:- 2 ] + "out" ):
120
173
file_out = case [:- 2 ] + "out"
121
- verdict ,cpu_usage ,mem_usage ,return_status = judge_case (case ,file_out ,cpu_limit ,mem_limit ,executable ,out_limit = os .path .getsize (file_out ) * 4 )
174
+ verdict ,cpu_usage ,mem_usage ,return_status = judge_case (case ,file_out ,cpu_limit ,mem_limit ,executable ,checker , out_limit = os .path .getsize (file_out ) * 4 )
122
175
cpu_total += cpu_usage
123
176
mem_total = max (mem_usage ,mem_total )
124
177
status_mask |= verdict .value
0 commit comments