精進環境を自動化しました

May 3, 2020 13:49 compro

こんにちは。ますぐれです。一人暮らしを始めました。

本日は前回に引き続き競プロの環境をさらに自動化していったのでその成果を報告します。

今回やったこと

今回は普段の問題を解くときにも自動提出がしたいということで、その際に必要なアレコレを全部自動化しました。 具体的には問題用のフォルダ作成、サンプルダウンロード、コンパイル、サンプルテスト、提出コードの作成、提出を自動化しました! その結果めっちゃ快適な環境が生まれたのでご報告します。

サンプルダウンロード、サンプルテスト、提出

これらの部分に関しては@kmykさんのonline-judge-tools/ojを利用しています。順番にoj doj toj sが対応しています。最初にサンプルを落としてくる際にはURLが必要なのですが、実行したフォルダをキャッシュしておいてくれるのでその後はURLの記載は基本的に不要です。(フォルダ名をtmpみたいなのにして複数の問題で使いまわすとキャッシュが上手く効かなくなってしまいます)

自動化で一番面倒くさい部分だと思うので、こういうライブラリを整備していただけるのはとても嬉しいです。開発にもjoin出来たらいいんですけど現状ちょっと手を出せないので その代わりに布教を続けています。

この部分だけだったら上のライブラリを導入するだけでどの環境にも簡単に導入できます。オススメです。

フォルダ作成、コンパイル、提出コードの作成

online-judge-toolsを使う際は問題ごとにフォルダを分けることが推奨されているんですが、毎回作るのも面倒なので自動化しています。で、ちょっとコードを書くんだったらファイルの監視をして、保存されたタイミングでコンパイルと提出コードの作成する部分もやっちゃうかと思ってそこまで自動化しました。

監視の部分はこんな感じのシェルスクリプトを書いています。更新日時が変更されていたらビルドし直して提出するべきコードを生成するって感じですね。やっぱりホットリロードはあると断然便利なので幸せです。

#!/bin/sh
INTERVAL=1 #監視間隔, 秒で指定
last=`ls -l --full-time tmp.cpp | awk '{print $7}'`
while true; do
        sleep $INTERVAL
        current=`ls -l --full-time tmp.cpp | awk '{print $7}'`
        if test $last != $current ; then
                echo ""
                echo "updated: $current"
                last=$current
                eval "g++-9 -std=c++17 -I ../../lib/ -Wall -Wextra -fuse-ld=gold -fsanitize=undefined tmp.cpp && oj-bundle -I '../../lib/' tmp.cpp > submit.cpp"
        fi
done

ちなみにフォルダ名は手打ちです。本当はURLの末尾からフォルダ名を生成するのがいいような気もしているんですが、面倒だったのでそこまではやってません。あとloginに対応していないところでもloginを打ってエラーを吐いたりしています。これもドメインを見て識別すべきかなあと思いつつ、動いてしまっているのでOKってなっています。

使い方

ぼくはVSCodeを使っているんですが、VSCodeはターミナルをSplitできる機能があるのでターミナルを2個立てて使っています。ファイル監視に1つ、テスト実行や提出用にもう1つって感じです。

具体的には./gen.sh {URL} {folder_name}を片方で実行し、もう片方で生成されたフォルダに入ってoj tとかoj sとかを打っています。こうするとVSCodeの画面上だけで全ての操作が完結するので問題を解くことだけに集中することができます。

終わりに

競技プログラミングも楽しいんですが、競技プログラミングをする環境を作るのもエンジニアリングって感じでまた違った面白さがあります。

二個も自動化記事を投げてしまったんですが、最近は結構アルゴリズムやデータ構造も勉強しているので、そこら辺の話も投稿出来たらなあと思っています。