vimでAtCoderするときに楽したい
vimってめちゃめちゃ速くコードをかけるということを最近実感しました。というのも、授業の一環で行われたペアプログラミングで、vimを使ってるつよつよerの人が謎コマンドを大量に駆使して高速でコードを書いていたからです。
そこで僕は、これを競技プログラミングに取り入れたらとても高速に問題をACできるのではないだろうか、と考えました。しかし、それには弊害も伴うのでそれらを解決していこう というのが今回の記事の内容です。
vimにしたことで不便になったこと
元々僕はIntellJ系のIDEであるCLionを学割で使用していました。それと比べてvimで不便になったなと思うことは
- ビルド&実行が1クリック or 1コマンドで実行できない
- 標準入力をテキストファイルから取ることができない
- ファイル全体のコピペがめんどくさい
などが挙げられます。そこで今回は、これらを解決していきます。
その前に:vimでできるようになったこと
今までIntellJでは「自分自身をincludeすることにより、テンプレファイルを下に持っていく」というテクニックをすると、警告が出てしまうので使えませんでした。
しかし、vimにしたことによりこれらはなくなりました。そこでまずはそれの導入を行います。
#if !__INCLUDE_LEVEL__
#include __FILE__
void solve(){
}
ファイルの先頭はこのようにしました。つまり、初回読み込み時は#include __FILE__
で自分自身をincludeした後に、solve関数を定義するということです。
mainではなくsolve関数を用意した理由は下で説明しますが、この関数内で処理を実行していきます。
#else
#include <bits/stdc++.h>
//中略
void solve();
int main(){
cin.tie(0); ios::sync_with_stdio(0);
solve();
return 0;
}
#endif
先程の分岐により、コンパイラ側ではelseの先がこちら側がファイルの一番先頭であると認識されるため、いつも書いてるテンプレをそのまま書いた上で、solve関数をプロトタイプ宣言します。。
その後main関数を実行した上で、cin/coutが速くなるおまじないをします。このように、毎回main関数で実行するコードもテンプレ化できるようにするために、solve関数を使用しました。
これでら、3行目からコーディングしながら、テンプレも使うことができるようになります。
ビルド&実行が1クリックでできない
この問題を解決するのは非常に簡単です。今回は、makefileにコンパイルオプションを書いた上で、makeコマンド→実行 をshファイルに記述しました。
1.makefileを書く
GNUmakefileというファイルを作り、中にこんな感じに書きます。
atcoder:AtCoder.cpp
g++ -Wall -std=c++20 -D LOCAL AtCoder.cpp
-D LOCAL
とすることにより、ローカル環境のみ動くコードというものが作れるようになっています。これはこの後重要になります。
2.shファイルを書く
先程はビルド先ファイルを指定していないので、./a.out
に生成されるはずです。よって、makeコマンドと合わせて
make
./a.out
とすれば良いです。僕は予測変換が効きやすようにmake_and_start.sh
という名前をつけましたが、好きな名前でいいです。
標準入力をテキストファイルから受け取れない
元々僕はIDEの機能を使って入力をinput.txt
から受け取っていました。しかしその方法はvimではできないので、別の方法を使用することにしました。
./a.out < input.txt
でも確かにできますが、それだとビルドせずに単体で実行したい場合は不便です(という理由をつけただけで、忘れてました)。
そこで、C++ファイル内で読み込むようにするために、main関数を以下のように変更します。
#include <fstream> //こいつも追記
int main(){
#ifdef LOCAL
ifstream inputFile("input.txt");
cin.rdbuf(inputFile.rdbuf());
#else
cin.tie(0);
ios::sync_with_stdio(0);
#endif
solve();
return 0;
}
AtCoderのオンラインジャッジでもinput.txtから読み込むのはまずいですから、#ifdef LOCAL
を使うことによってローカルのみにしています。ifstreamで読み込んで、rdbufでcinの入力受け取りを標準入力から変更しています。
ただし残念なことに、高速化するおまじないとは競合してしまうので、高速化はオンラインジャッジのみとしました。これにより、input.txtからcinできるようになります。
ファイル全体のコピペがめんどくさい
vimで全部をコピーする簡単な方法があったらぜひ教えてください。分からなかったので、ターミナルでファイルの内容をコピーできるようにしたいと思って調べたら、以下の情報が出てきました。
pbcopy < AtCoder.cpp
しかし、僕が普段使ってるArchにpbcopyはなく、かわりにxclipというものが使えるというのがわかったので、xclipを使って
xclip -selection clipboard < AtCoder.cpp
というコマンドをshファイルに追加しました。これで、ビルド時に自動でクリップボードにコピーしてくれるので、後は成功したら提出欄に貼り付けるだけですみます。非常にスマートです。
終わりに
vimを便利に使えるようにするために、周辺環境を整えてみました。肝心のvimはまだあまり慣れていないので、これから使いこなせるように練習していきます。
Discussion
vimでファイル全体をコピーするには、vimのコマンドである
:%y
を使用するとよいです!
vimでヤンク時にレジスタだけでなく、OSのクリップボードにも値を入れるために
vimrcに
set clipeboard+=unnamed
を記載する必要があります
なるほど、そんな設定があるのですね。ありがとうございます!