競技プログラミング向けC++環境をWebサービス開発のノウハウで作ってみた 1.使い方
最近競技プログラミングを始めた開発チームの下田です。
会社でもプログラミングを主に行う仕事をしていますが、卸・仕入れサイト スーパーデリバリーといったサービス開発とはまったく違う難しさがあり、四苦八苦しながらも楽しんでいます。
会社でソフトウェア開発を行う場合、開発を簡単に始められるように、会社で開発環境を用意します。競技プログラミングサイトでもオンラインジャッジシステムが用意されていますが、機能が物足りない場合が多く、各自で用意することが多いのではないでしょうか。
自分で使うために、2020年現在でアプリケーション環境構築のデファクトスタンダードとなっている、Dockerを使用したC++向けサンドボックス環境のnekosunaを作成しましたので、ご紹介したいと思います。
起動方法
1. Dockerのインストール
Dockerを使用します。インストール方法は省略します。
2. docker-compose.ymlをダウンロード
このファイルをダウンロードします。Gitを使える方はリポジトリのサイズも小さいので、リポジトリごとcloneすると良いと思います。
git clone https://github.com/onfi/nekosuna.git
3. dockerコンテナの立ち上げ
2でダウンロードしたdocker-compose.ymlを置いたディレクトリに移動し、docker-composeで立ち上げます。イメージのダウンロード完了後にコンテナが起動し、下記のように表示されれば立ち上げ完了です。
docker-compose up
使い方
起動できたら、localhostの8080番ポートにアクセスしてみましょう。
http://localhost:8080/
コード編集
ブラウザ上でコードを書けます。sublime textライクなキーバインドとなっているので、Ctrl + Alt + ↓カーソルでマルチカーソルの開始などを行えます。
ビルド
build & runボタンをクリックすると、作成したC++のコードがコンパイルします。コンパイルエラーがあると、左下のCompile resultエリアにエラーが表示されるとともに、エラー行をハイライトします。
テスト
右下にtestエリアがあります。左のSTDINテキストボックスにプログラムの標準入力に渡す値を入力し、右のexpect STDOUTに標準出力の期待結果を入力します。build & runボタンをクリックすると、コンパイルに成功したらテストを実行し、テストごとに結果を表示します。
成功した場合は、実行時間を表示します。実行している端末のスペックに依存するので、参考程度に使ってください。
失敗した場合、期待結果との差を表示します。また、入力欄の下に実際に標準出力のデータを表示します。
約5秒で実行を打ち切ります。実行を打ち切った場合、TLEと表示します。
テストデータのロード
loadボタンをクリックするとダイアログが表示され、jsonでテストデータを入力してロードすることができます。下記のフォーマットで入力してください。
[
["STDIN0", "STDOUT0"],
["STDIN1", "STDOUT1"],
["STDIN2", "STDOUT2"],
...
]
問題ページをパースして、このjson形式にフォーマットするプログラムを作成しておくと便利です。
ライブラリの利用
2020年9月より、オンラインで参加できるプログラミングコンテストのAtCoderでAtCoder Libraryを使用できるようにルールが改定されました。
このAtCoder LibraryやBoost C++ Librariesを使用できます。
// AtCoder Library
#include <atcoder/modint>
#include <iostream>
using namespace std;
using namespace atcoder;
// 998244352で割った余りを扱う型
using mint = modint998244353;
int main() {
// 998244353で割った余り、998244353未満ならそのまま表示する
mint m = 998244352;
cout << m.val() << endl;
int n;
cin >> n;
m += n;
// STDIN - 1になる
cout << m.val() << endl;
}
// Boost C++ Libraries
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
// 多倍長整数
namespace mp = boost::multiprecision;
int main() {
// 何桁でも扱える。STDINに100桁渡せばそのまま表示する
// 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
mp::cpp_int m;
cin >> m;
cout << m;
}
注意事項
自分で使うためにローカルのネットワークでの運用を想定して作成しています。セキュリティ対策はしていませんので、インターネット上にサービスとして公開してはなりません。
ある程度テストは行っていますが、アプリケーションの特性上、予期せぬ動作をすることがあります。このアプリケーションは参考程度に使用し、最終的には参加されるプログラミングコンテストのジャッジシステムを利用してください。
まとめ
意外とプログラミングするための環境構築は手間がかかります。1台のPCにセットアップするだけなら大した手間ではありませんが、チームでの開発や端末入れ替えするたびに構築し直すので、積み重なると大変なことになります。
最近はInfrastructure as Code、つまり環境構築手順をコードにする方法をよく使います。複数台にセットアップする場合にも、同じことを繰り返さないDRY原則を適用できるのです。
ラクーンの技術戦略部でも、スーパーデリバリーやPaidといった内製しているサービスの開発環境も、Dockerや仮想マシンを使って利用しています。今回はそのノウハウを使って競技プログラミング向けの開発環境を作成しました。
今回は使い方をご説明しましたが、このアプリケーションの設計時にどんなことを考えて作ったのか、数回の連載で解説しようと思います!