RubyプログラマがAtCoderの環境をatcoder-cliとonline-judge-toolsで快適にしてみた

# 0.  はじめに
みなさん競技プログラミングしていますか？
普段コードを書く仕事をしている方は騙されたと思ってぜひ挑戦してみてほしいです！

私もコンテストに挑戦したくて[AtCoder](https://atcoder.jp/home)を始めることにしました
ビギナー向け、上級者向けなど色んなレベルのコンテストが**毎週開催**されてます
私は業務でRubyを使っているのでRubyで始めました

ただ少しだけ試しにAtCoderをやってみて気づいたのですがWeb上での操作性がイマイチ😓

ちょっとコードを書いて動作テストするのもサンプルの入力例をコピペしなきゃいけなかったり、
そもそもWeb上でボタンポチポチしてるのが本当にナンセンス
コードも動作テストもファイルの提出もコマンドラインですべて完結させたい！！

ってわけで調べてみたらありました（開発者様、本当にありがとうございます。みんなでスター送りましょう👏）
- [atcoder-cli](https://github.com/Tatamo/atcoder-cli)
- [online-judge-tools](https://github.com/online-judge-tools/oj)

本記事は上記のツールを用いて**RubyでAtCoderを快適にできるようにする手順を紹介**します

もう両方導入してるよ！って方は[もっと快適にカスタマイズ（For Ruby）](#3--もっと快適にカスタマイズfor-ruby)まで飛ばしてください🙇‍♂️

# 1. インストール
では早速 `atcoder-cli` と `online-judge-tools` をインストールしていきます
[公式インストールガイド](http://tatamo.81.la/blog/2018/12/07/atcoder-cli-installation-guide/)を見れば問題なくインストール出来ると思います

参考までに私がやった手順を載せておきます（Macでの例）

### 必要なツール群の確認
無い場合は適宜インストールしてください
```bash
# 私の環境の場合

# Homebrew
$ brew -v
Homebrew 3.5.2
Homebrew/homebrew-core (git revision 4366462849d; last commit 2022-06-22)
Homebrew/homebrew-cask (git revision e4d7e9f18f; last commit 2022-06-22)

# npm
$ npm -v
6.14.15

# pip3
$ pip3 -V
pip 22.0.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
```
### インストール
上記が問題ないようなら早速インストールしましょう
```bash
# atcoder-cli インストール
$ npm install -g atcoder-cli
# インストール確認
$ acc -v
2.2.0

# online-judge-tools インストール
$ pip3 install online-judge-tools
# インストール確認
$ oj --version
online-judge-tools 11.5.1 (+ online-judge-api-client 10.10.0)
```

これでインストール完了です✌️

# 2. 初期設定
### AtCoderにログイン
次に初期設定としてコマンドライン上でAtCoderにログインします
[まだAtCoderのアカウント作ってない方はコチラ](https://atcoder.jp/register?continue=https%3A%2F%2Fatcoder.jp%2Fhome)

```bash
# atcoder-cliでAtCoderにログイン
$ acc login
username: AtCoderのユーザー名
password: パスワード
OK

# online-judge-toolsでもAtCoderにログイン
$ oj login https://beta.atcoder.jp/
・
・
username: AtCoderのユーザー名
password: パスワード
[NETWORK] POST: https://atcoder.jp/login
[NETWORK] redirected to: https://atcoder.jp/home
[NETWORK] 200 OK
[WARNING] AtCoder says: × Welcome, AtCoderのユーザー名.
[INFO] Welcome,
[NETWORK] GET: https://atcoder.jp/contests/agc001/submit
[NETWORK] 200 OK
[SUCCESS] You have already signed in.
[INFO] save cookie to: /Users/xxxxxx/Library/Application Support/online-judge-tools/cookie.jar
```

### ディレクトリ作成
ログイン出来たら任意の場所にディレクトリを作成します
このディレクトリ配下にコンテストディレクトリを作成していきます
参考までに私はホームディレクトリに作成しました
```bash
$ mkdir atcoder
```

### RubyのバージョンをAtCoderと合わせる
RubyでAtCoderやるなら環境はちゃんと揃えましょう
[AtCoderの採点システムではRubyの2.7.1を使用している](https://atcoder.jp/contests/practice/rules)みたいなのでそれに合わせます

```bash
# 自身のrbenvに2.7.1がない場合はまずインストール
$ rbenv install 2.7.1

# さきほど作成したディレクトリに移動してローカルRubyバージョンを固定
$ cd atcoder
$ rbenv local 2.7.1
```
これで初期設定完了です✌️

# 3.  もっと快適にカスタマイズ（For Ruby）
ここまで設定したら問題なく快適に使えるはずですが、
**毎回どの問題をダウンロードするか**とか
**毎回提出用ファイルを作ったり**とか
**毎回打つコマンドのオプションが面倒**とか
デフォルト設定よりももうちょっと便利にしたい！って部分をそれぞれカスタマイズしていきます

### コンテストディレクトリ作成時に問題をすべてダウンロード
`aｃｃ n コンテストID` でコンテスト用のディレクトリを作成した際にどの問題をダウンロードするか選択するのですが、これが毎回面倒( `acc n` は `acc new` の略) 
1問でも全問でもダウンロードは一瞬なので全問ダウンロードするようにしちゃいましょう
下記を実行
```bash
$ acc config default-task-choice all
```
これでatcoder-cliの設定が**毎回全問ダウンロード**の設定に書きかわりました（今後このコマンドは打たなくて大丈夫）

### テンプレートの作成
毎回提出用のファイルを一から作るのは面倒！ナンセンス！
main.rbって名前で提出用ファイルを自動作成＆毎回打つであろう `gets.chomp〜` も最初から書いてある状態にしちゃいましょう
```bash
# atcoder-cli設定ディレクトリに移動
$ cd `acc config-dir`
$ pwd
Users/xxxxxx/Library/Preferences/atcoder-cli-nodejs

# テンプレート作成
$ mkdir ruby && cd ruby
$ touch template.json
$ touch main.rb
```

ファイルの中身は下記をコピペ
```json:template.json
{
  "task":{
    "program": ["main.rb"],
    "submit": "main.rb",
	"testdir": "test"
  }
}
```

```ruby:main.rb
#!/usr/bin/env ruby
input = gets.chomp.split("")
```
atcoder-cli設定ディレクトリの最終的な構成は下記を参考に
```bash:~/Library/Preferences/atcoder-cli-nodejs配下のディレクトリ構成
.
├── config.json # 全般設定
├── ruby # 今回作ったRuby用の設定ディレクトリ
│   ├── main.rb # 言語ごとの提出ファイルのテンプレート
│   └── template.json # 言語ごとの設定
└── session.json
```

次にこのテンプレートをデフォルト設定にします
```bash
$ acc config default-template ruby
```
これで `--template` オプションをつけなくてもデフォルトで毎回Rubyテンプレートを使用するようになります

ちなみにこれらの設定をすべてやると`~/atcoder配下はこんな感じの構成になります
```bash:~/atcoder配下のディレクトリ構成
.
├── .ruby-version # Rubyバージョンファイル
└── abc200 # コンテストID（acc newするたびに増えていく
    ├── a # 問題（問題をダウンロードするたびにa,b,c,d…と増えていく）
    │   ├── main.rb # 各問題ごとの提出用ファイル
    │   └── test # 各問題ごとのテスト用ディレクトリ
    │       ├── sample-1.in # 入力例1
    │       ├── sample-1.out # 出力例1
    │       ├── sample-2.in # 入力例2
    │       └── sample-2.out # 出力例2
    ├── b
　　　　　　　　・　　　　　　├── main.rb
　　　　　　　　・　　　　　　・
```
シンプルでわかりやすくて管理もしやすそう

## 動作テストを楽にする
AtCoderをやっていると合間に何度も動作テストをするかと思います（少なくとも私は）

テスト自体はonline-judge-toolsで簡単にコマンドライン上で出来るのですが、
毎回毎回 `oj t -c " ruby main.rb" -d test` と打たなくてはなりません

コマンド履歴で出るとしても長いのは煩わしいですよね

ここで先ほど**提出ファイル名とテスト用ディレクトリ名を設定**したのが効いてきます！

**提出ファイル名とテスト用ディレクトリが毎回同じなのでスニペットツールなどで登録しちゃえば良い**のです！
（ネットで見てると[Dash](https://kapeli.com/dash)や[Alfredのスニペット機能](https://www.alfredapp.com/)を使用してる人が多い印象。まあお好みで）
ちなみに私は `.zshrc` にaliasとしてそのまま登録しちゃいました（今のところ問題なし）

```vim:~/.zshrc
alias ojt='oj t -c " ruby main.rb" -d test'
```

これで `ojt` を打つだけでテスト実行が出来るようになりました✌️
楽ちん〜

## コードの提出を楽にする
これも今までの設定をしていたら実は完了しています

先ほど `template.json` で設定した
`"submit": "main.rb"` が提出するファイル名の指定になってます

つまり実際にコードを書くファイルと提出ファイル名が一緒なので
**`acc s` だけでコードの提出が出来ます**👏
※ `acc s` は `acc submit` の略です

# 4. まとめ
実際にどう使うかのまとめです
なんと**普段のルーティン操作はこれだけ**です

1. `acc n ContestID`（コンテストの問題全件ダウンロード）

2. 問題を解く（main.rbにコードを書く）

3. `ojt`（動作テスト）

4. 問題が解けるまで2と3を繰り返す

5. `acc s`（コードの提出）

6. 次の問題を解く（以下繰り返し）

つまりコマンドとして使うのは `acc n` と `ojt` と `acc s` の3つだけ！
これは楽すぎますね👏

私は普段Vimを使ってるので完全にコマンドライン上のみでAtCoderを楽しめるようになりました👏

:::note info
ちなみに他のコマンドを知りたい方は、公式チュートリアルがとてもわかりやすかったです
- [atcoder-cli公式チュートリアル](http://tatamo.81.la/blog/2018/12/07/atcoder-cli-tutorial/)
- [online-judge-tools日本語チュートリアル](https://github.com/online-judge-tools/oj/blob/master/docs/getting-started.ja.md)
:::

# 最後に
競技プログラミングって考えるとハードル高いなぁって思うかもしれませんがアルゴリズムって面白いですよ😄
私はバリバリの文系ですがちょっと数学を学び直したいなと思うくらいドハマリしてます

冒頭でも言いましたが、**普段コードを書く仕事をしているなら騙されたと思ってぜひ挑戦してみてほしい**です

みなさん普段は各言語のフレームワークやIDEを使って開発していると思うので、普段の仕事に活かせるかって言われると微妙ですけどｗ
私の上長曰く、**実際直接的にはほぼ役に立たないがここぞという時の自信だったり底力になる**とのこと

たしかに以前アルゴリズムの勉強で [paizaスキルチェック](https://paiza.jp/challenges) を半年ほどやり続けてましたが、
ああいうメソッドあったよな？とか
このループ処理無駄が多いかも？とか
これもっと綺麗にシンプルに書けそうとか
業務が飛躍的に楽になるわけではないですが底力にはなってた気はします🤔（浅いｗ）

まあ一番はやってて楽しいのでそれでヨシですね！

ここまで読んでくださりありがとうございます
みなさんが快適なAtCoderライフを送れることを祈ってます🙌


# 番外編
ちなみにアルゴリズムは奥が深いので本を読んでみても面白いかも
[アルゴリズム図鑑](https://www.amazon.co.jp/%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E5%9B%B3%E9%91%91-%E7%B5%B5%E3%81%A7%E8%A6%8B%E3%81%A6%E3%82%8F%E3%81%8B%E3%82%8B26%E3%81%AE%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0-%E7%9F%B3%E7%94%B0-%E4%BF%9D%E8%BC%9D/dp/4798149772/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3HUFT7R3LIFA1&keywords=%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E5%9B%B3%E9%91%91&qid=1655903295&sprefix=%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E5%9B%B3%E9%91%91%2Caps%2C216&sr=8-1)
これはわかりやすくて面白かった
私の上長からもお薦めしていただいた本です

子供が見ても面白いだろうなと思うので娘たちが小学生くらいになったら見せてみようかな