-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhowtojudge.html
151 lines (113 loc) · 5.37 KB
/
howtojudge.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<title>スペシャルジャッジの実装例</title>
<p>
<a href="https://yukicoder.me/problems/no/5000">仕様についてはこちらを参照</a>
</p>
<h3 class="shadow">実装例</h3>
<p>
例えば、以下の問題のスペシャルジャッジを作る場合を考えます。
</p>
<blockquote>
整数 $N$ が与えられる。次の条件を満たす 2 つの整数 $A$, $B$ を半角スペース区切りで出力せよ。<br>
$N = A + B$
</blockquote>
<pre>
#include <bits/stdc++.h>
int main(int argc, char** argv) {
// テストケースの入力ファイルの input stream
std::ifstream input_ifs(argv[1]);
// テストケースの出力ファイルの input stream
std::ifstream output_ifs(argv[2]);
// 提出されたコードのファイルの input stream
std::ifstream code_ifs(argv[3]);
// スコアファイル(スコア問題のみ利用)の output stream
std::ofstream score_ofs(argv[4]);
// 標準入力(std::cin)に提出コードでの標準出力が渡される
// ------
// 「提出コードでの標準出力」から2つの整数を読み込む
// 半角スペース区切り・改行区切りのどちらでも可
int a, b;
std::cin >> a >> b;
// int型なので、32bit整数で表現出来ない数値は読み込めない
// 脆弱性を突かれないためにも、制約を決めて、問題文に記載するべき。
// 例えば、-100以上100以下の整数しか受け付けない場合、以下のように記述すれば良い。
// abortは、メッセージを標準エラーに出力して異常終了(コード1)する関数。
if (-100 > a || a > 100) abort("invalid a");
if (-100 > b || b > 100) abort("invalid b");
// 「テストケースの入力ファイル」から1つの整数を読み込む
int n;
input_ifs >> n;
// a + b == n でないならば
if (a - n != -b) {
// Wrong Answer として、ジャッジプログラムを終了する。
// メッセージを記載しておくと、デバッグしやすい。
std::cerr << "a=" << a << ", b=" << b << ", n=" << n << std::endl;
abort("Wrong Answer: a + b = n");
}
// assertを使って以下のように記載しても良い。
// ただしassertは、コンパイル時のマクロ定義によっては無効化されることがある。
// assert(a - n == -b);
// 正解なので、正常終了する。
return 0;
}
</pre>
<p>
また、スペシャルジャッジ問題の場合、入力制約のみならず、出力制約にも気を配りましょう。
</p>
文字列を受け取る場合 <code>std::setw</code> を使い、入力数を制限することも検討してください。<br>
<a href="https://cpprefjp.github.io/reference/iomanip/setw.html">https://cpprefjp.github.io/reference/iomanip/setw.html</a><br>
特にユーザーコードがバグにより異常に多い出力になってしまった場合で<code>TLE</code>にならないまま ジャッジ側に渡された場合<code>J_TLE</code>
と言われる場合があります。<br>
通常の問題の場合<code>J_TLE</code>と出るのは好ましくないです。 <br>
文字数も問題の判定の要素の場合は<code>N+1</code>文字で制限するなどで検討してください。<br>
ランダムに<code>J_TLE</code>が出る場合は、ジャッジサーバーの増強を考えますのでご連絡ください。<br>
※空ファイルで十分ですのでテスト出力ファイルをおいてください。テスト出力ファイルが存在しない場合はジャッジされません。<br>
<br>
<h3 class="shadow">その他の言語の実装例</h3>
<h4 class="shadow">Python3</h4>
<p>
きっと誰かが書いてくれます(書きました)
</p>
<pre>
import sys
#テストケースの入力ファイル
input_file = open(sys.argv[1],mode='r',encoding='utf-8')
#テストケースの出力ファイル
output_file = open(sys.argv[2],mode='r',encoding='utf-8')
#提出されたコードのファイル
code_file = open(sys.argv[3],mode='r',encoding='utf-8')
#スコアファイル
score_file = open(sys.argv[4],mode='w',encoding='utf-8')
###########################################################
#標準出力はopen(0)で開いて、多く出力されていないかも見たほうが良い。
std_input = open(0).read().split()
if len(std_input)!=2:
#標準エラー出力をしておくと便利である。
sys.stderr.write("too many output!\n")
#必ず例外を発生させる。
raise Exception
#実は、std_inputの各要素には改行がついていることがあるので文字列として扱う場合は注意
a,b=map(int,std_input)
N=int(input_file.read().split()[0])
if a+b!=N:
sys.stderr.write(f"a={a},b={b},N={N}\n")
#Exceptionのあとにメッセージを入れることも可能
raise Exception("a+b!=N")
#エラーがなくてもエラー出力しておくとデバックしやすい
sys.stderr.write(f"success,a={a},b={b},N={N}\n")
#ファイルは必ず閉じる(閉じなくてもエラーが起きたりはしない)
#with を使うと閉じなくてよいので便利
input_file.close()
output_file.close()
code_file.close()
score_file.close()
</pre>
<br>
<h4 class="shadow">Ruby</h4>
<p>
あとで書きます
</p>
<br>
<h4 class="shadow">Go</h4>
<p>
<a href="https://yukicoder.me/problems/no/5000/code">こちら</a>
</p>