Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No format analysis for ongoing ABC contests #286

Merged
merged 3 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions atcodertools/atcoder_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def main():
if len(sys.argv) < 2 or sys.argv[1] not in ("gen", "test", "submit", "codegen", "compile", "set", "version"):
print("Usage:")
print("{} gen -- to generate workspace".format(sys.argv[0]))
print(
"{} codegen -- to generate code for one problem".format(sys.argv[0]))
print(
"{} compile -- to compile codes in your workspace".format(sys.argv[0]))
print("{} test -- to test codes in your workspace".format(sys.argv[0]))
Expand Down
3 changes: 2 additions & 1 deletion atcodertools/common/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ def from_name(cls, name: str):
name="python",
display_name="Python",
extension="py",
submission_lang_pattern=re.compile(".*Python \\(3.*|.*Python \\(CPython 3.*"),
submission_lang_pattern=re.compile(
".*Python \\(3.*|.*Python \\(CPython 3.*"),
default_code_generator=python.main,
default_template_path=get_default_template_path('py'),
compile_command="python3 -mpy_compile {filename}.py",
Expand Down
42 changes: 41 additions & 1 deletion atcodertools/constprediction/constants_prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ def __init__(self, cands):
self.cands = cands


class FailingToKnowFormatAnalysisAllowedByRuleError(Exception):
def __init__(self, reason):
self.reason = reason


MOD_ANCHORS = ["余り", "あまり", "mod", "割っ", "modulo"]
DECIMAL_ANCHORS = ["誤差", " error "]
LIMIT_ANCHORS = ["時間制限", "Time Limit"]
Expand Down Expand Up @@ -206,6 +211,26 @@ def normalize(sentence):
raise MultipleModCandidatesError(limit_cands)


def predict_is_format_analysis_allowed_by_rule(html: str) -> bool:
soup = BeautifulSoup(html, "html.parser")
url_meta_tag = soup.find("meta", property="og:url")
if url_meta_tag is None:
raise FailingToKnowFormatAnalysisAllowedByRuleError(
"No meta tag detected, which is important as a clue to know if the input analysis is allowed.")

# ABC is the target of "No LLM rules" by AtCoder (See https://info.atcoder.jp/entry/llm-abc-rules-ja or https://info.atcoder.jp/entry/llm-abc-rules-en)
is_target_contest_of_no_llm_rule = "/contests/abc" in url_meta_tag["content"]

# If there is no virtual standings link, assume it's ongoing.
is_ongoing_contest = len([tag for tag in soup.find_all(
"a") if "/standings/virtual" in tag.get("href", "")]) == 0

if is_target_contest_of_no_llm_rule and is_ongoing_contest:
return False

return True


def predict_constants(html: str) -> ProblemConstantSet:
try:
yes_str, no_str = predict_yes_no(html)
Expand Down Expand Up @@ -233,4 +258,19 @@ def predict_constants(html: str) -> ProblemConstantSet:
"two or more candidates {} are detected as limit".format(e.cands))
timeout = None

return ProblemConstantSet(mod=mod, yes_str=yes_str, no_str=no_str, judge_method=judge, timeout=timeout)
try:
is_format_analysis_allowed_by_rule = predict_is_format_analysis_allowed_by_rule(
html)
except FailingToKnowFormatAnalysisAllowedByRuleError as e:
logger.warning(
"Failed to know whether format analysis is allowed by the contest rules -- ", e.reason)
is_format_analysis_allowed_by_rule = None

return ProblemConstantSet(
mod=mod,
yes_str=yes_str,
no_str=no_str,
judge_method=judge,
timeout=timeout,
is_format_analysis_allowed_by_rule=is_format_analysis_allowed_by_rule,
)
4 changes: 3 additions & 1 deletion atcodertools/constprediction/models/problem_constant_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ def __init__(self,
yes_str: str = None,
no_str: str = None,
judge_method: Judge = None,
timeout: float = None
timeout: float = None,
is_format_analysis_allowed_by_rule: bool = None,
):
self.mod = mod
self.yes_str = yes_str
self.no_str = no_str
self.judge_method = judge_method
self.timeout = timeout
self.is_format_analysis_allowed_by_rule = is_format_analysis_allowed_by_rule
9 changes: 8 additions & 1 deletion atcodertools/fmtprediction/predict_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ def __init__(self, cands):
self.cands = cands


def predict_format(content: ProblemContent) -> FormatPredictionResult:
class PredictionNotAllowedError(Exception):
pass


def predict_format(content: ProblemContent, is_format_analysis_allowed_by_rule: bool) -> FormatPredictionResult:
if not is_format_analysis_allowed_by_rule:
raise PredictionNotAllowedError

input_format = content.get_input_format()
samples = content.get_samples()

Expand Down
14 changes: 9 additions & 5 deletions atcodertools/tools/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from atcodertools.config.config import Config
from atcodertools.constprediction.constants_prediction import predict_constants
from atcodertools.fmtprediction.models.format_prediction_result import FormatPredictionResult
from atcodertools.fmtprediction.predict_format import MultiplePredictionResultsError, NoPredictionResultError, predict_format
from atcodertools.fmtprediction.predict_format import MultiplePredictionResultsError, NoPredictionResultError, PredictionNotAllowedError, predict_format
from atcodertools.tools import get_default_config_path
from atcodertools.tools.envgen import USER_CONFIG_PATH, get_config, output_splitter
from atcodertools.tools.utils import with_color
Expand Down Expand Up @@ -89,19 +89,23 @@ def emit_info(text):
emit_error("Failed to download samples.")
raise e

constants = predict_constants(content.original_html)

try:
prediction_result = predict_format(content)
prediction_result = predict_format(
content, constants.is_format_analysis_allowed_by_rule or False)
emit_info(
with_color("Format prediction succeeded", Fore.LIGHTGREEN_EX))
except (NoPredictionResultError, MultiplePredictionResultsError) as e:
except (NoPredictionResultError, MultiplePredictionResultsError, PredictionNotAllowedError) as e:
prediction_result = FormatPredictionResult.empty_result()
if isinstance(e, NoPredictionResultError):
msg = "No prediction -- Failed to understand the input format"
else:
elif isinstance(e, MultiplePredictionResultsError):
msg = "Too many prediction -- Failed to understand the input format"
elif isinstance(e, PredictionNotAllowedError):
msg = "Format prediction is skipped because it's not allowed by AtCoder rules (At least not allowed in ongoing ABC contests) -- See https://info.atcoder.jp/entry/llm-abc-rules-en"
emit_warning(with_color(msg, Fore.LIGHTRED_EX))

constants = predict_constants(content.original_html)
code_generator = config.code_style_config.code_generator
with open(template_code_path, "r") as f:
template = f.read()
Expand Down
14 changes: 9 additions & 5 deletions atcodertools/tools/envgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
create_code
from atcodertools.fmtprediction.models.format_prediction_result import FormatPredictionResult
from atcodertools.fmtprediction.predict_format import NoPredictionResultError, \
MultiplePredictionResultsError, predict_format
MultiplePredictionResultsError, PredictionNotAllowedError, predict_format
from atcodertools.tools import get_default_config_path
from atcodertools.tools.models.metadata import Metadata
from atcodertools.tools.utils import with_color
Expand Down Expand Up @@ -117,19 +117,23 @@ def emit_info(text):
code_file_path,
new_path))

constants = predict_constants(content.original_html)

try:
prediction_result = predict_format(content)
prediction_result = predict_format(
content, constants.is_format_analysis_allowed_by_rule or False)
emit_info(
with_color("Format prediction succeeded", Fore.LIGHTGREEN_EX))
except (NoPredictionResultError, MultiplePredictionResultsError) as e:
except (NoPredictionResultError, MultiplePredictionResultsError, PredictionNotAllowedError) as e:
prediction_result = FormatPredictionResult.empty_result()
if isinstance(e, NoPredictionResultError):
msg = "No prediction -- Failed to understand the input format"
else:
elif isinstance(e, MultiplePredictionResultsError):
msg = "Too many prediction -- Failed to understand the input format"
elif isinstance(e, PredictionNotAllowedError):
msg = "Format prediction is skipped because it's not allowed by AtCoder rules (At least not allowed in ongoing ABC contests) -- See https://info.atcoder.jp/entry/llm-abc-rules-en"
emit_warning(with_color(msg, Fore.LIGHTRED_EX))

constants = predict_constants(content.original_html)
code_generator = config.code_style_config.code_generator
with open(template_code_path, "r") as f:
template = f.read()
Expand Down
Loading
Loading