問題を読み、コードを書き、入力例で確認し、全部OKだった。
意気揚々と提出したら 無慈悲な「WA」 。
どこが間違っているかもわからない・・・。どうしよう・・・。
そんな時の対処法をお伝えします。
なお、この記事は初心者~灰色の方向けに書いていますので、茶色以上の人には当たり前に感じることが多いと思います。
また、難易度が高めの問題で起こりがちなWAも書きません。
茶色以上の人は勝手に頑張ってくれ。
そもそもサンプル通ってますか?
自分の手元でテストしたときは全部合ってる!と思ってたけど、
「Yes」を出力する問題で「YES」を出力しているとか
「Hello!」を出力する問題で「Hello」を出力しているとか
そういったしょーもねえミスが無いかをまず確認しましょう。
コンテスト中の提出でもサンプル(入力例)が合っているかは提出画面の「詳細」から確認できます。
コードの見直しをする
まずはコードの見直しです。自分が意図した動作どおりのコードになっているか確認しましょう。
変数名間違い
変数名、aとaaとaaaとかでやってませんか?
xとXで別のものを表したりしていませんか?
今すぐやめましょう。
こういった変数名の付け方をしているとaに代入すべきところをaaにしてしまったとか、変なミスに繋がりがちです。
普通はサンプルを試した時に気づくんですが、何故かサンプルは通っちゃうことがあるんですね・・・。
ans(answerの意味)とかcountとか、なるべくなにを表しているのかわかりやすい変数名にしましょう。
i,j見間違い
以下のコードを見てください。
for i in range(N):
for j in range(N):
ans+=A[i][i]
ん?ってなりましたか?
iとjのループを回しているのにA[i][i]になっていますね。
ほんとはA[i][j]でないといけないところ、A[i][i]にしてしまうとかはありがちです。
なんせiとj、めっちゃ似ている。
iとkにしましょう。jには故郷の村を焼かれたというくらいの気持ちで避けましょう。
少数が含まれる計算
28*(25/100)はいくらでしょうか?
計算してみましょう。
print(28*(25/100))
【出力結果】
7.0
OK。では25*(28/100)はいくらでしょう。
print(25*(28/100))
【出力結果】
7.000000000000001
は?
はい、これが少数計算の誤差です。コンピューターは無限小数を扱えないので誤差が出る可能性があります。
「/」(割り算)は極力避けましょう。可能な限り「//」(割り算の商)を使いましょう。
例外の場合として出力結果の指定に「出力との絶対誤差または相対誤差が10^(−6)以下のとき正解と判定される。」とあればばんばん使ってOKです。
WAになるケースを探す
コードは合ってそうだなとなったらどのケースでWAになっているか確認します。
制約の端っこ確認
制約が1≤N≤10^5なら必ずN=1のケースを確認しましょう。
可能ならN=10^5のケースもやっておきましょう。
制約の端はコーナーケース(例外的な処理が必要なケース)になりがちです。
偶数の場合、奇数の場合両方試す
問題によりますが入力が偶数の場合と奇数の場合で別の処理が必要なことがあります。
偶数の場合、奇数の場合両方を入力して試してみましょう。
もうとにかくいろいろ試す
上記2つでは合ってそうなのに!となったらとにかく色々なパターンを試してみましょう。
自分で正答の値がわかるパターンを作って、実行して確認を繰り返しまくります。
このケースはここで処理しているから通るはず、というケースも必ず試しましょう。
人間は愚かなので思いもよらないミスがあるものです。
自動化してしまう(上級者向け)
例えば以下のような問題の場合を考えます。
A=A1,A2,A3,...,ANについて、(Ai,Aj)の最大公約数が1になる組の個数を出力せよ。
1≤N≤10^5
1≤Ai≤10
(i,j)全組の最大公約数を確認すると計算量がO(N^2)になるので当然Nが最大のケースでTLEします。が、少なくとも答えは出せますね。
このようにゴリ押しで答えを出すコードと、自分で書いたコード両方を実行してみて出力の一致しないケースを探すという方法です。
入力の値もランダムで作れるようにしてしまえばいろいろなケースを高速で試すことができます。
最後の手段 テストケースの確認
コンテスト中ではなく、過去問を解いている時の方法です。
AtCoderは公式がテストケースを公開しています。
コンテスト後だいたい1週間から2週間程度で公開されるようです。
これでWAになるケースを直接確認します。
正解を確認するのも大事ですが、 なぜ間違っているのか を確認するのも大事です。
皆さんも良い競プロライフを!