はじめに
この記事は競技プログラミングを始めたばかりの人に伝えたいことアドベントカレンダー6日目の記事です!
アドベントカレンダー初めてです!始めたばかりの人向けということで軽い内容をお届けします。
追記
@mkawa2さんにコメントにて、AtCoderだけではなくcodeforcesとyukicoderでも使えるという報告をいただきました!
この記事ではPythonのみを取り扱っていますが@superrino130さんがRuby、@uhooiさんがSwiftでの実装の記事を書いてくれました。
こんなやらかししたことない…?
~AtCoderコンテスト中~
(ABC228B問題より)
(あれ!?出力例と一致しないぞ!)
(printを挿入して処理が思い通りか確認してみよう)
(えーっと…2つ目のインデックスが最初に参照されて…って問題文は1-indexで実装は0-indexなのにindexを変換していない!)
(入力を0-indexに変換しよう)
(テストしてみて…)
(よしっ!思ったとおりに動いてるし、出力も正しいぞ!)
(他のサンプルケースも一致したから提出しよう!)
(あれっ!!??WA!!??あっっ!!デバッグのprint消すの忘れてた!!!)
ということやったことありませんか?僕は今までに5回くらいやった気がします()
このミスを標準エラー出力を使うことによって回避しようということです。
標準エラー出力でデバッグをしよう
まず標準エラー出力というのは簡単に言うとエラーが出力されるところです。
例えば先程の例の入力を数字以外にするとエラーは次のようになります。
AtCoderのコードテストは標準出力と標準エラー出力が別れていてどちらがどちらかわかりやすいですね。
このようにエラーが標準エラー出力に出力されていることがわかります。
AtCoderのジャッジでは標準出力のみを読み取っており標準エラー出力は無視されます。つまり、デバッグのための出力を標準エラー出力に出力すれば消し忘れによるWAは起こりえません(TLEはありえる)。
Pythonでの標準エラー出力のしかた
Pythonでは標準エラー出力は以下のようにします。
import sys
print("error", file=sys.stderr)
記述しやすいように関数化しよう
毎回上記のように書くのはめんどくさい!と思ったので関数化しました。
import sys
def error(*args, end="\n"): print(*args, end=end, file=sys.stderr)
この関数をプログラムの一番上とかに入れておけばerror
関数をprint
関数を使用するのと同じ要領で標準エラー出力に記述することができます。
※*args
ってなんやねんって思った人。関数の引数の前に*
をつけると引数何個投げてきてもいいよって意味になります。受け取った引数はタプルとして保持します。逆にprint(*args)
のように関数を呼び出すときはタプルのargs
の一つ一つの要素を引数として渡してねって意味になります。似ているものとして**kwargs
というものもあります。もっと詳しく知りたい人はPythonの可変長引数(*args, **kwargs)の使い方 | note.nkmk.me等で調べてみてください。
追記、WAは大丈夫だけどTLEには気をつけなければいけない
この記事内でもTLEは起こり得ると書きましたが、コメントでも@YTOKさんに指摘されましたので実際どの程度気をつけなければいけないのかちゃんと調べました。
pass
するだけのfor
ループと標準エラー出力をするfor
ループを実行して実行時間を確認しました。
コードです(見なくていいです)
import sys
import time
def error(*args, end="\n"): print(*args, end=end, file=sys.stderr)
print("標準エラー出力なし")
for i in [5, 6, 7]:
N = 10 ** i
t1 = time.time()
for _ in range(N):
pass
print(f"10^{i} : {time.time() - t1:.4f} s")
print("標準エラー出力あり")
for i in [5, 6, 7]:
N = 10 ** i
t1 = time.time()
for j in range(N):
error(j)
print(f"10^{i} : {time.time() - t1:.4f} s")
この結果をまとめますと、
10^7以上 → 完全アウト
10^6 → 複数入れると高確率でTLE、消すほうが無難
10^5以下 → 気にする必要なし
という感じです!
最後に
需要があるのか謎ですが、便利!使お!って思ってくれたら幸いです。
あと、もっといい方法とか関連してやってること等あればぜひ教えて下さい。