VSCodeでの競プロ環境構築 (Julia)
この記事では、Julia言語でVSCode上に競技プログラミング環境を構築し、AtCoderに簡単に提出できる状態を作ります。
AtCoder以外のコンテストサイト等についてはあまり説明しません。
環境としてはWSLを想定していますが、そうでなくても殆ど問題ないと思います。
また、この記事ではWSLのインストールやVSCodeのインストール等については説明しません。
競プロ用ディレクトリの作成
適当な競プロ用のディレクトリ(contests
とか)を作成します。
特に言及しない限り、この記事内では競プロ用ディレクトリをカレントディレクトリとします。
Juliaup のインストール
Juliaupはバージョン管理ツールで、Juliaのバージョン切り替えを簡単にできるものです。
Pythonでいうところのpyenvのようなものです。
インストールはこれに書いてある通りに、
curl -fsSL https://install.julialang.org | sh
を実行します。
出てくる文言を読んで、特に問題が無ければ、 Proceed with installation
を選択して、インストールをします。
少し待つと、インストールが終わり、環境変数 PATH
を再読み込みしてください、と出ると思うので、 .bashrc
なり .profile
なりを再読み込みします。
Juliaupがきちんとインストール出来ているかを確認するために以下のコマンドを実行します。
juliaup status
うまくいっていれば、下記のような表示が出て、最新のJuliaがインストールされていることがわかるはずです。
Default Channel Version Update
-------------------------------------------------
* release 1.9.2+0.x64.linux.gnu
念のため、Juliaの方もきちんとPATHが通っているか確認します。
julia --version
これで、上記のバージョンと同じもの(この記事の場合であれば1.9.2)が表示されていれば、問題ありません。
AtCoderでのJuliaのバージョンや使用可能なパッケージはここに書かれているので、これと同じ環境にすると、バージョン違いやパッケージの有無で WA
になりにくくすることができると思います。
VSCodeにおけるJuliaの設定
Julia のインストール
拡張機能拡張機能 Juliaをインストールをして、適当なJuliaのファイル(拡張子が .jl
)を開き、下の青いステータスバーに Julia env: v1.9
などと表示されていれば大丈夫です。
確認のために適当なコードをファイルに保存して実行します。
とりあえず、Juliaのコード例に載っている、マンデルブロ集合の描画プログラムを試します。
function mandelbrot(a)
z = 0
for i=1:50
z = z^2 + a
end
return z
end
for y=1.0:-0.05:-1.0
for x=-2.0:0.0315:0.5
abs(mandelbrot(complex(x, y))) < 2 ? print("*") : print(" ")
end
println()
end
# Taken from: https://rosettacode.org/wiki/Mandelbrot_set#Julia
Alt
+Enter
で実行することができるので、実行すると以下のようにマンデルブロ集合が出力されます。
出力
**
******
********
******
******** ** *
*** *****************
************************ ***
****************************
******************************
******************************
************************************
* **********************************
** ***** * **********************************
*********** ************************************
************** ************************************
***************************************************
*****************************************************
***********************************************************************
*****************************************************
***************************************************
************** ************************************
*********** ************************************
** ***** * **********************************
* **********************************
************************************
******************************
******************************
****************************
************************ ***
*** *****************
******** ** *
******
********
******
**
フォーマッタの設定
Shift
+Alt
+F
で整形できるようになっていますが、保存時に整形されるようにすると便利なので、設定をしていきます。
.vscode
ディレクトリ内の .settings.json
に "editor.formatOnSave": true
を追記します。
これにより Ctrl
+S
で整形されるようになります。
フォーマッタのルールを調整したい場合は .JuliaFormatter.toml
を作成し、これに従って調整をします。
例としては以下のようにすればよいです。
always_for_in = true
remove_extra_newlines = true
online-judge-tools の設定
ここでは online-judge-tools/oj
と online-judge-tools/template-generator
の2つを導入します。
これらについての説明は、以下のURLを見てください。
- https://github.com/online-judge-tools/oj/blob/master/docs/getting-started.ja.md
- https://github.com/online-judge-tools/template-generator/blob/master/README.ja.md
導入方法についてもそれぞれの GitHub に書いてありますが、この記事でも一応記述しておきます。
これらのツールの導入のために pip
や pipenv
などを使えるようにしてください。
インストールについての説明は省略します。
また、この記事では pipenv
を使ってインストールするので、それ以外の場合は適宜読み替えてください。
oj のインストール
下記のコマンドでインストールします。
pipenv install online-judge-tools
oj でのログイン
ログインをしなければ提出などができないので、設定していきます。
pipenv run oj login https://atcoder.jp
上記のコマンドを入力すると、AtCoderでのユーザー名とパスワードを求められるので入力します。
template-generator のインストール
基本的にはここに従います。
下記のコマンドでインストールします。
pipenv install online-judge-template-generator
このツールを使うことで、問題に合わせた入出力が書かれたファイルを自動生成できるのですが、そのような設定を Julia でするには、かなりカスタマイズが必要なため、これは行いません。どの問題でも同じファイルを用意することで対応します。
VSCodeにおけるonline-judge-toolsの設定
AtCoder以外の方法も示した方が良いと思い、Codeforcesの設定もしていますが、CodeforcesではJuliaが使えなさそうです。
後からこのことに気がつきましたが、一応残しておきます。
シェルスクリプトの作成
まず scripts
ディレクトリを作成し、その中に submit.sh
という名前でファイルを作成します。
そのファイルに以下のように書きます。
#!/bin/bash
submit_file=$1 # relative file path (${service_name}/${contest_id}/${problem_id}/main.jl)
service_name=${submit_file%%/*}
contest_id=$(basename ${submit_file%/*/*})
problem_id=$(basename ${submit_file%/*})
case "$service_name" in
"AtCoder" )
problem_url="https://atcoder.jp/contests/${contest_id}/tasks/${problem_id}"
;;
"Codeforces" )
problem_url="https://codeforces.com/contest/${contest_id}/problem/${problem_id}"
;;
esac
pipenv run oj s -y ${problem_url} ${submit_file}
その後 chmod 755 scripts/submit.sh
を実行してパーミッションを変更します。
同じように scripts
ディレクトリの中に dltest.sh
という名前でファイルを作成し、以下のように記述して、パーミッションを変更します。
#!/bin/bash
problem_dir=$1 # relative directory path (${service_name}/${contest_id}/${problem_id})
service_name=${problem_dir%%/*}
contest_id=$(basename ${problem_dir%/*})
problem_id=${problem_dir##*/}
test_dir=${problem_dir}/test
case "$service_name" in
"AtCoder" )
problem_url="https://atcoder.jp/contests/${contest_id}/tasks/${problem_id}"
;;
"Codeforces" )
problem_url="https://codeforces.com/contest/${contest_id}/problem/${problem_id}"
;;
esac
if [ ! -e ${test_dir} ]; then
pipenv run oj d -d ${test_dir} ${problem_url}
fi
テンプレート等の作成
~/.config/online-judge-tools/
ディレクトリに prepare.config.toml
を以下の内容で作成します。
contest_directory = "{service_name}/{contest_id}"
problem_directory = "{problem_id}"
[templates]
"main.jl" = "main.jl"
そして ~/.config/online-judge-tools/template/
ディレクトリに main.jl
を作成します。
これがテンプレートファイルになるので、使いやすいように変更してください。
function main()
n = parse(Int, readline())
end
main()
タスクの登録
.vscode
ディレクトリに tasks.json
を作成し、以下のように記述して保存します。
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "download test cases",
"command": "${workspaceFolder}/scripts/dltest.sh",
"args": [
"${relativeFileDirname}"
]
},
{
"type": "shell",
"label": "do oj-prepare",
"command": "pipenv",
"args": [
"run",
"oj-prepare",
"${input:service_url}/${input:contest_id}"
]
},
{
"type": "shell",
"label": "do oj test",
"command": "pipenv",
"args": [
"run",
"oj",
"t",
"-c",
"julia ${file}",
"-d",
"${fileDirname}/test"
],
"dependsOn": [
"download test cases"
],
"group": {
"kind": "test",
"isDefault": true
},
"presentation": {
"focus": true
}
},
{
"type": "shell",
"label": "submit",
"command": "${workspaceFolder}/scripts/submit.sh",
"args": [
"${relativeFile}"
]
}
],
"inputs": [
{
"id": "service_url",
"type": "pickString",
"description": "Contest site URL",
"options": [
"https://atcoder.jp/contests",
"https://codeforces.com/contest"
],
"default": "https://atcoder.jp/contests/"
},
{
"id": "contest_id",
"type": "promptString",
"description": "Contest ID"
}
]
}
Ctrl
+Shift
+P
を押して Tasks: Run Task
を選択すると、登録したタスクが出てきて、選択するだけで実行できるようになっています。
一応、使用するタスクを説明しておくと、
-
do oj-prepare
: コンテストのディレクトリ作成とテストケースのダウンロード -
do oj test
: 入力例などによるテスト -
submit
: コードの提出
となっています。
他のタスクは直接使用することはないと思います。
始まっていないコンテストで do oj-prepare
はできないので注意してください。
タスクをショートカット一発で実行できるようにする場合は keybindings.json
に適当に追記すればよいです。
あとは実際に問題を解いて提出してみてください。
うまくいかないとき
この設定をしてしばらく遊んでいると、何個か問題が出てきたので追記しておきます。
随時更新する予定です。
REPLの起動時にpython環境を読み込んでしまう
venv環境等を使っていると、ターミナルの起動時に pyenv shell x.y.z
みたいなのが出てきて、これが標準入力を邪魔するときがあります。
この読み込みを無くすために settings.json
に "python.terminal.activateEnvironment": false
を追記します。
REPL起動時の最初の一行目が無視される
Inline evaluation: readline() is broken で議論されています。
どうにかするのは難しいそうなので Alt
+Enter
の代わりに Ctrl
+F5
を使うといいかもしれません。
REPLを使う理由が強くなければ基本的にこの対策でよさそうです。
Discussion