shu8Creamのブログ

競プロブログ。

競プロer向け知っておきたい便利なLinuxコマンド

本記事は競プロ Advent Calendar 2022、12/15日分の記事です。
前日14日の記事はこちらから、翌日16日はこちらからどうぞ!

最近、AtCoder以外にも多様なコンテストに出るようになってLinuxコマンドを駆使して色々と調べることが増えてきたのでまとめてみます。 ここでいうLinuxコマンドは、Macでいうところのターミナル、WindowsでいうところのWSLで使用するコマンドを指しています。(Linuxってターミナルだっけ?)

time

時間を計測するコマンドです。実行する時につけておくだけで実行時間がわかるので便利です。 オンラインジャッジがなくて、手元の実行結果を提出するタイプのコンテスト(Meta(Facebook) Hacker Cupなど)だとMAXケースでどれぐらい時間がかかるか測っておくと安心です。 プログラム自体の実行時間は、userを見れば良いです。オンラインジャッジへの提出を考えている場合、ジャッジサーバーと環境が全く違う場合もあるので参考程度と考えておきましょう。

使用例

$ time ./a.out < ./input > ./output

real    0m0.182s
user    0m0.059s
sys     0m0.062s
$ time python A.py < ./input > ./output

real    0m0.451s
user    0m0.057s
sys     0m0.068s

diff

ファイル同士の差分を比較するコマンドです。競プロで使うシチュエーションとしては、愚直解は自明だけど高速化が必要なケースで、愚直解の答えと高速化した解を比較する時に使えたりします。このコマンドはオプション必須だと思っていて、よく使うのはq, yオプションです。

# file1   #file2
1 2 3      1 2 3
4 5 6      4 5 6
4 5 6      7 8 9
1 2 3      2 2 3

使用例

# オプションなし
$ diff ./file1 ./file2
3,4c3,4
< 4 5 6
< 1 2 3
---
> 7 8 9
> 2 2 3
# qオプション
$ diff ./file1 ./file2 -q
Files ./file1 and ./file2 differ  # 違う時はこう出る(差分がなければ何もなし)
# yオプション
$ diff ./file1 ./file2 -y
1 2 3                                       1 2 3
4 5 6                                       4 5 6
4 5 6                                     | 7 8 9      # 差分があるところにパイプが出る
1 2 3                                     | 2 2 3
# yオプション2
$ diff ./file1 ./file2 -y --suppress-common-lines
4 5 6                                     | 7 8 9      # 差分だけ出せる
1 2 3                                     | 2 2 3

tee

ログ出力関連のコマンドです。
ログ出力と聞くと競プロと関係なさそうに感じますが、ファイル書き込みと考えると利用シーンが思いつくのではないでしょうか?
echoなどのコマンドの後ろにパイプで接続するとファイル書き込みができて便利です。

echo hogehoge | tee log.txt

こちらの場合は常に上書きされるので、追記したいときは

echo hogehoge | tee -a log.txt

のように-aオプションをつけます。
競プロでの使い所としては、AHCなどのマラソンコンテストで1テストケースの実行結果を保存して、改善前後で比較したい時などは手っ取り早くコマンドでファイル書き込みができて便利です。
ちなみに、こちらのコマンドは標準出力を書き込むことになるので、標準エラー出力もファイルに書き込みたい場合は

echo hogehoge 2>&1 | tee log.txt

こんな感じにすると良いです!

xargs

標準入力から引数を受け取って実行するコマンドです。実行するだけであれば、普通に実行ファイルを実行すれば良いということになってしまいますが、このコマンドでは並列化処理ができます。ヒューリスティックコンテストでたくさんのテストケースを実行したいけど、1000個のテストケースを実行すると単純計算で1時間くらいかかる...というような時に実行時間を短く収めることができます(PCのスペック次第...)。

# 実行コマンド
seq 0 999 | xargs -P4 -I{} ./exec.sh {} # 0~999の入力ファイルを実行

上記の実行コマンドのように実行します。exec.shファイルに実行したいコマンドをシェルスクリプトで書いています。今回のコマンドはAtCoder Heuristic Contest(AHC)で、C++の./a.outやPythonコードを実行するファイルをexec.shとして実行した例です。実行ファイルは好きなものに置き換えてください。
具体的に中身を解説すると、seqコマンドで0~999までの数値を順に出力し、それはパイプ(| ←この縦棒のこと)で右のコマンドへ渡します。
次にxargsコマンドで./exec.shの実行を行います。-Pオプションがこのコマンドの肝で、このオプションを使うことで自動で並列化して実行することができます。今回は-P4としているので4並列で実行してくれます。
PCスペックによりますが、単純計算で1000ケースを直列実行した時の4分の1の時間で実行が完了します(実際はもう少し時間がかかると思います)。 並列数は任意に指定できますが、スペックが足りないとうまく動作しない可能性もあるので、自分のPCと相談して使用すると良いです。 マラソン系のコードだとうまく計算リソースが使えず、スコアがガクンと落ちる場合もあるので注意です。
最後のオプションですが、-Iオプションで./exec.shの実行コマンドの引数にテストケースの番号(0-999)を渡すことで、合計1000ケースをまとめて実行しようとしています。テストケース番号はコマンド中の{}が置き換えられて順に実行されます。

exec.shファイルに何書けばいいんだー?、ヒューリスティックコンテストで実際どう使うんだー?と思ったあなたは、こちらの記事をご覧ください

おわりに

以上が競プロで使えるLinuxコマンド紹介でした。
ヒューリスティックコンテスト向けが多いですね。僕は、MHCに参加した時に必要性を強く感じたので、普段AtCoderCodeforcesアルゴリズムコンテストのみに参加していれば、必要性があまり感じられないかもしれないです...
そんな方も色々なコンテストに参加して、深い競プロ沼へ飛び込みましょう。