7
7
from atcodertools .common .judgetype import ErrorType , NormalJudge , DecimalJudge , Judge
8
8
from atcodertools .common .logging import logger
9
9
from atcodertools .constprediction .models .problem_constant_set import ProblemConstantSet
10
+ import math
10
11
11
12
12
13
class YesNoPredictionFailedError (Exception ):
@@ -19,6 +20,12 @@ def __init__(self, cands):
19
20
self .cands = cands
20
21
21
22
23
+ class MultipleLimitCandidatesError (Exception ):
24
+
25
+ def __init__ (self , cands ):
26
+ self .cands = cands
27
+
28
+
22
29
class NoDecimalCandidatesError (Exception ):
23
30
pass
24
31
@@ -31,6 +38,7 @@ def __init__(self, cands):
31
38
32
39
MOD_ANCHORS = ["余り" , "あまり" , "mod" , "割っ" , "modulo" ]
33
40
DECIMAL_ANCHORS = ["誤差" , " error " ]
41
+ LIMIT_ANCHORS = ["時間制限" , "Time Limit" ]
34
42
35
43
MOD_STRATEGY_RE_LIST = [
36
44
re .compile ("([0-9]+).?.?.?で割った" ),
@@ -47,6 +55,10 @@ def __init__(self, cands):
47
55
re .compile ("1e(-[0-9]+)" )
48
56
]
49
57
58
+ LIMIT_STRATEGY_RE_LIST = [
59
+ re .compile ("([0-9.]+)\s*sec" )
60
+ ]
61
+
50
62
51
63
def is_mod_context (sentence ):
52
64
for kw in MOD_ANCHORS :
@@ -62,6 +74,13 @@ def is_decimal_context(sentence):
62
74
return False
63
75
64
76
77
+ def is_limit_context (sentence ):
78
+ for kw in LIMIT_ANCHORS :
79
+ if kw in sentence :
80
+ return True
81
+ return False
82
+
83
+
65
84
def predict_modulo (html : str ) -> Optional [int ]:
66
85
def normalize (sentence ):
67
86
return sentence .replace ('\\ ' , '' ).replace ("{" , "" ).replace ("}" , "" ).replace ("," , "" ).replace (" " , "" ).replace (
@@ -161,6 +180,32 @@ def normalize(sentence):
161
180
return NormalJudge ()
162
181
163
182
183
+ def predict_limit (html : str ) -> Optional [int ]:
184
+ def normalize (sentence ):
185
+ return sentence .replace ('\\ ' , '' ).replace ("{" , "" ).replace ("}" , "" ).replace ("," , "" ).replace (" " , "" ).lower ().strip ()
186
+
187
+ soup = BeautifulSoup (html , "html.parser" )
188
+ sentences = soup .get_text ().split ("\n " )
189
+ sentences = [normalize (s ) for s in sentences if is_limit_context (s )]
190
+
191
+ limit_cands = set ()
192
+
193
+ for s in sentences :
194
+ for regexp in LIMIT_STRATEGY_RE_LIST :
195
+ m = regexp .search (s )
196
+ if m is not None :
197
+ extracted_val = float (m .group (1 ))
198
+ limit_cands .add (extracted_val )
199
+
200
+ if len (limit_cands ) == 0 :
201
+ return None
202
+
203
+ if len (limit_cands ) == 1 :
204
+ return math .floor (list (limit_cands )[0 ] * 1000.0 + 0.5 )
205
+
206
+ raise MultipleModCandidatesError (limit_cands )
207
+
208
+
164
209
def predict_constants (html : str ) -> ProblemConstantSet :
165
210
try :
166
211
yes_str , no_str = predict_yes_no (html )
@@ -181,4 +226,11 @@ def predict_constants(html: str) -> ProblemConstantSet:
181
226
"two or more candidates {} are detected as decimal values" .format (e .cands ))
182
227
judge = NormalJudge ()
183
228
184
- return ProblemConstantSet (mod = mod , yes_str = yes_str , no_str = no_str , judge_method = judge )
229
+ try :
230
+ timeout = predict_limit (html )
231
+ except MultipleLimitCandidatesError as e :
232
+ logger .warning ("limit prediction failed -- "
233
+ "two or more candidates {} are detected as limit" .format (e .cands ))
234
+ timeout = None
235
+
236
+ return ProblemConstantSet (mod = mod , yes_str = yes_str , no_str = no_str , judge_method = judge , timeout = timeout )
0 commit comments