開発堕ち
まあ AI に聞いただけなんだけど
https://archive.topcoder.com/ProblemArchive
SRM フォルダを作って、中に solution.cpp (解法,これは本番通りにclassで書く) と tests.txt (各問題を開いて全てをコピペしたら良い) と judge.py (中身は後述) を置く
python3 judge.py をしたら、
=== testproblem | 3 Cases === Case 00: [ TLE ] (3.0s exceeded) Case 01: [ TLE ] (3.0s exceeded) Case 02: [ OK ] (0.0000s) =================================== 最終結果まとめ =================================== OK: 1 | NG: 0 | TLE: 2 | RE: 0 Max Time: 3.0000s ===================================
みたいなのが出てくる
judge.py の中身はこちら
import os
import subprocess
import re
import time
# ----------------------------------------------------------------
# 1. 判定ロジック(double誤差判定)
# ----------------------------------------------------------------
def check_double_error(actual_str, expected_str):
try:
a_vals = re.findall(r"-?\d+\.?\d*(?:e[-+]?\d+)?", actual_str)
e_vals = re.findall(r"-?\d+\.?\d*(?:e[-+]?\d+)?", expected_str)
if len(a_vals) != len(e_vals): return False
for av, ev in zip(a_vals, e_vals):
a, e = float(av), float(ev)
if a == e: continue
abs_err = abs(a - e)
rel_err = abs_err / max(abs(e), 1e-18)
if min(abs_err, rel_err) > 1e-9: return False
return True
except: return False
# ----------------------------------------------------------------
# 2. 問題文のパース
# ----------------------------------------------------------------
def parse_all_content(content):
config = {}
try:
config['class'] = re.search(r'Class:\s*(\w+)', content).group(1)
config['method'] = re.search(r'Method:\s*(\w+)', content).group(1)
params_raw = re.search(r'Parameters:\s*(.*)', content).group(1)
config['args_types'] = [p.strip() for p in params_raw.split(',')]
config['returns'] = re.search(r'Returns:\s*([\w<> ]+)', content).group(1).strip()
num_args = len(config['args_types'])
except: return None, []
examples_part = content.split("Examples", 1)[1] if "Examples" in content else content
lines = [l.strip() for l in examples_part.split('\n') if l.strip()]
cases = []
for i, line in enumerate(lines):
if "Returns:" in line:
expected = line.replace("Returns:", "").strip()
args = lines[i - num_args : i]
if len(args) == num_args: cases.append({"args": args, "expected": expected})
return config, cases
def format_cpp_value(raw_val, type_str):
raw_val = raw_val.strip()
if "vector" in type_str: return raw_val if "{" in raw_val else "{" + raw_val + "}"
if "string" in type_str: return raw_val if raw_val.startswith('"') else f'"{raw_val}"'
return raw_val
# ----------------------------------------------------------------
# 3. メイン処理
# ----------------------------------------------------------------
def run_judge():
if not (os.path.exists("tests.txt") and os.path.exists("solution.cpp")):
print("Error: tests.txt または solution.cpp が見つかりません。"); return
with open("tests.txt", "r", encoding="utf-8") as f:
content = f.read()
config, cases = parse_all_content(content)
if not config or not cases:
print("Error: 問題文を解析できませんでした。"); return
# C++ドライバー生成
switch_cases = ""
for i, case in enumerate(cases):
cpp_args = [format_cpp_value(v, t) for v, t in zip(case['args'], config['args_types'])]
switch_cases += f"""
case {i}: {{
auto start = chrono::high_resolution_clock::now();
auto res = sol.{config['method']}({", ".join(cpp_args)});
auto end = chrono::high_resolution_clock::now();
chrono::duration<double> diff = end - start;
print_val(res);
cout << "\\nTIME: " << fixed << setprecision(6) << diff.count() << endl;
break;
}}"""
driver_code = f"""
#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <chrono>
#include "solution.cpp"
using namespace std;
template<typename T> void print_val(const T& v) {{ cout << v; }}
template<> void print_val(const double& v) {{ cout << fixed << setprecision(15) << v; }}
template<typename T> void print_val(const vector<T>& v) {{
cout << "{{";
for(size_t i=0; i<v.size(); ++i) {{
if(i>0) cout << ", ";
print_val(v[i]);
}}
cout << "}}";
}}
int main(int argc, char** argv) {{
if(argc < 2) return 1;
int id = atoi(argv[1]);
{config['class']} sol;
switch(id) {{
{switch_cases}
default: break;
}}
return 0;
}}
"""
with open("temp_driver.cpp", "w", encoding="utf-8") as f:
f.write(driver_code)
ext = ".exe" if os.name == 'nt' else ".out"
cmd_ext = "./test" + ext if os.name != 'nt' else "test" + ext
# コンパイル
comp = subprocess.run(["g++", "-O3", "-std=c++20", "temp_driver.cpp", "-o", "test"+ext], capture_output=True)
if comp.returncode != 0:
print("=== Compile Error ==="); print(comp.stderr.decode()); return
print(f"=== {config['class']} | {len(cases)} Cases ===\n")
stats = {"OK": 0, "NG": 0, "TLE": 0, "RE": 0, "max_time": 0.0}
is_double = "double" in config['returns'].lower()
for i in range(len(cases)):
try:
# 3.0秒のタイムアウトを設定
res = subprocess.run([cmd_ext, str(i)], capture_output=True, text=True, timeout=3.0)
output_lines = res.stdout.strip().split('\n')
actual = ""
elapsed = 0.0
for line in output_lines:
if "TIME: " in line:
elapsed = float(line.replace("TIME: ", ""))
else:
actual = line
stats["max_time"] = max(stats["max_time"], elapsed)
expected = cases[i]["expected"]
success = check_double_error(actual, expected) if is_double else (actual.replace(" ","") == expected.replace(" ",""))
if success:
print(f"Case {i:02}: [ OK ] ({elapsed:.4f}s)")
stats["OK"] += 1
else:
print(f"Case {i:02}: [ !! ] NG ({elapsed:.4f}s)")
print(f" 期待: {expected} | 出力: {actual}")
stats["NG"] += 1
except subprocess.TimeoutExpired:
print(f"Case {i:02}: [ TLE ] (3.0s exceeded)")
stats["TLE"] += 1
stats["max_time"] = max(stats["max_time"], 3.0)
except:
print(f"Case {i:02}: [ RE ] (Runtime Error)"); stats["RE"] += 1
print(f"\n" + "="*35 + f"\n 最終結果まとめ\n" + "="*35)
print(f" OK: {stats['OK']} | NG: {stats['NG']} | TLE: {stats['TLE']} | RE: {stats['RE']}")
print(f" Max Time: {stats['max_time']:.4f}s")
print("="*35)
if __name__ == "__main__":
run_judge()バグってるかは知りません、スペシャルジャッジは見なかったことにしよう
本当に問題文コピペだけでいけるのは偉いと思った、room移動で10分待ちなんてなかったんや
おまけ
javascript:(function(){var tables=document.getElementsByTagName('table');for(var i=0;i<tables.length;i++){var rows=tables[i].rows;if(rows.length>0){var lvlIdx=-1;var catIdx=-1;var headerCells=rows[0].cells;for(var j=0;j<headerCells.length;j++){var txt=headerCells[j].textContent.replace(/\s+/g,' ').trim();if(txt.includes('Div. 1 Level'))lvlIdx=j;if(txt.includes('Categories'))catIdx=j;}if(lvlIdx!==-1){for(var r=0;r<rows.length;r++){var row=rows[r];if(catIdx!==-1&&row.cells[catIdx])row.cells[catIdx].style.display='none';if(r>0){var levelCell=row.cells[lvlIdx];if(levelCell){var val=levelCell.textContent.trim();if(val!=='3')row.style.display='none';}}}}}}})();で問題タグを消してDiv.1 hardだけ残せるようになった
chromeで、アーカイブをブックマークして編集でこれを打っておいて、アーカイブリンク開いてからブックマークを押すと動いた