Help us understand the problem. What is going on with this article?

VSCodeで競技プログラミング向けC++の作業環境をつくってみた。

VSCodeで競技プログラミング向けC++環境のおすすめ環境

とても参考になった以下の記事を自分なりに改良してみました。
競技プログラミングやLinux環境を始めたばかりなのでアドバイス等ありましたら、コメントの方よろしくお願いします。

Visual Studio Codeで競プロ環境構築(導入編)
Visual Studio Codeで競プロ環境構築(実践編)
VSCodeでの競プロ向けC++環境をWSLにRemote Developmentする形で作る

基本的には記事通りですが、過去に書いたコードをわかりやすく分類できるようにしました。
参考にされる方がいましたら幸いです。

準備

まず、Visual Studio Codeで競プロ環境構築(導入編)を参考に、環境構築を頑張ってください。

次にVisual Studio Codeで競プロ環境構築(実践編)を参考にC++環境を整えてください。

今回は自動でサンプルケースを検証する機能を付けたいので、こちらの自動ツールを使う。(Visual Studio Codeで競プロ環境構築(実践編)の最後の最後の自動でサンプルケースを検証するで使っているツールです。)online-judge-toolsを導入

ソースコードをビルドするまで

フォルダ構成

VSCodeのワークスペースフォルダはwslのルートからこの位置にあると思います。

フォルダー構成
wsl/
└── home/
    └── foo/
        └── workspace/

これをVSCodeのワークスペースに以下のような構造を創っていきます。

フォルダー構成
.workspace
├── Makefile  # 新規作成
├── scr  # 実行ファイル置き場(最初は中身が空)
│   ├── abc114_a # こんな名前のファイルが作られていく
│   └── abc114_b
├── cptest_atcoder.sh  # ツールを使ってデバッグする
├── atcoder.sh  # 新しいコンテスト用に使う
├── ord_source # 過去に解いた.cppを中に収納する
├── library
├── template
│   ├── temp.cpp # このファイルをコピーして問題用のファイルを作る
│   └── input.txt # ここに書いてある入力を使ってデバッグする
├── work
│   └── Contestname # このフォルダの名前がコンテスト名になる
│        ├── a.cpp # ここで問題を解く
│        └── b.cpp
└── src  # ソースコード置き場 全部フラットに配置するように変更
    ├── bin # 実行ファイル置き場
    │    ├── a
    │    └── b
    └── test  # AtCorderから自動取得したテストケース置き場(最初は中身が空)
        ├── abc114_a # こんな名前のフォルダーやファイルが作られていく
        │   ├── sample-1.in
        │   ├── sample-1.out
        │   ├── sample-2.in
        │   └── sample-2.out
        └── abc114_b
            ├── sample-1.in
            ├── sample-1.out
            ├── sample-2.in
            ├── sample-2.out
            ├── sample-3.in
            └── sample-3.out

cptest_atcoder.shとatcoder.shはあとでエイリアスを通します。

ビルドとデバッグ

次に.vscodeの中の設定ファイルを構築していきます。
とりあえずF5を押します。
C++ (GDB/LLDB)からのg++-7 build and debug active fileを押してみます。まあ、どれ選んでもいいです。

これで、.vscode/launch.json.vscode/tasks.jsonができているので、これらを編集します。

launch.json
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++-9 - アクティブ ファイルのビルドとデバッグ",
            "type": "cppdbg",
            "request": "launch",
            "program":"${workspaceFolder}/scr/bin/${fileBasenameNoExtension}",
            "args": [
                "<",
                "${fileDirname}/input.txt"
            ],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}/scr/bin",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "gdb の再フォーマットを有効にする",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "g++-9 build active file",
            "miDebuggerPath": "/usr/bin/gdb"
        }
    ]
}

初期ファイルとだいぶ変わっているので、気を付けてください。
`${workspaceFolder}とかのいみはVS Codeの設定をキレイに変数置換を参照するとわかりやすいと思います。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "test_atcorder_sample",
            "type": "shell",
            "command": "cptest ${workspaceFolderBasename}",
            "problemMatcher": [
                "$gcc"
            ]
        },
        {
            "label": "test_manual_input",
            "group": {
                "kind": "test",
                "isDefault": true
            },
            "type": "shell",
            "command": "make",
            "args": [
                "problem=${fileBasenameNoExtension}",
                "run"
            ]
        },
        {
            "type": "shell",
            "label": "cd",

            "command": "cd",
            "args": [
                "${workspaceFolder}"
            ],
        },

        {
            "type": "shell",
            "label": "g++-9 build active file",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "command": "make",
            "args": [
                "problem=${fileBasenameNoExtension}"
            ],
            "problemMatcher": [
                "$gcc"
            ],
            "dependsOn": [
                "cd"
            ]
        }
    ]
}

色々変わっているのでコピペおすすめです。
各要素の意味は書くのが面倒になってきたので調べてください。知っておくと、うまく動かなくなったときに自分で直せます。

Makefileがないと動かないので、Makefileを編集します。

# 例:
# make problem=a
# これでaという実行ファイルが作れる

# 例2:
# make problem=a run
# これでabc111_aという実行ファイルが作れて、input.txtを入力として受け取り動く

all: scr/bin/${problem}
.PHONY : all

# aという実行ファイルを作るためには./src/a.cppが必要
scr/bin/${problem}: work/*/${problem}.cpp
    g++ -g -O0 -std=c++14 -o scr/bin/${problem} work/*/${problem}.cpp

# aという実行ファイルを動かすためにはaが必要
run: scr/bin/${problem}
    ./scr/bin/${problem} < input.txt

サンプル検証するスクリプト

Visual Studio Codeで競プロ環境構築(実践編) - Qiita
を使わせてもらって、ちょっと変更して下記を作りました。
スクリプト内でログインするため、username、passwordを自分のものに書き換えてください。

cptest_atcoder.sh
#!/bin/bash
cd /home/foo/workspace
workpath="work/*"
folderpath=`find $workpath -type d`
contestname=`basename $folderpath`

problemfilepathes="work/*/*"
problempath=`find $problemfilepathes -type f -name \*${1}.cpp`
problemfile=`basename $problempath`
programname="${problemfile:0:1}"

problemname="${contestname}_${programname}"
echo "${contestname} ${programname}"


# 企業コンテストの場合、下記のようにtasksの前はハイフンになるため対策する
# https://atcoder.jp/contests/ddcc2020-qual/tasks/ddcc2020_qual_a

baseurl=${problemname:0:-2}
baseurlreplaced=${baseurl//_/-}

cd /home/foo/workspace
# 本番中に使うためにログインする
oj login -u username -p password "https://atcoder.jp/" 
# username, passwordは適切な文字列にする
oj login --check "https://atcoder.jp/"

queurl="https://atcoder.jp/contests/${baseurlreplaced}/tasks/${problemname}"

# testディレクトリがなければ取得する
if [ ! -e scr/test/${programname} ]; then
  oj dl -d scr/test/${programname}/ ${queurl} > /dev/null
fi

make "problem=${programname}"

oj test -c "./scr/bin/${programname}" -d scr/test/${programname}/

新規のコンテストを始める前に

新たにコンテストを始めるときにatcoder contestnameとすることで、
test/bin/の中身を消し、work内をord_sourceに移動。
templateから新しいコンテスト用のフォルダをwork内に配置するスクリプトを書きます。

atcoder.sh
#!/usr/bin/bash
cd /home/yudai/Atcoder_Cpp

rm -f scr/bin/* 
rm -f scr/test/* 

cp -r work/* ord_source/
rm -r work/*

cp -r template work/"$1"
cd work/"$1"

for index in a b c d e f
do
  cp temp.cpp $index.cpp 
done
rm temp.cpp

エイリアスの設定

エイリアスとは変数みたいなものでalias ll='ls -s'とすることでls -sというコマンドをllで実行できるようになります。

エイリアスは/home/user/.bashrcを書き換えることで設定します。
bashでsudo vi /home/user/.bashを実行し、

.bashrc
…
…
alias ll='ls -l'
alias cptest='/home/foo/workspace/cptest_atcoder.sh' # 追加
alias atcoder="/home/foo/workspace/atcoder.sh" # 追加

まとめ

始め方はまず、bashにatcoder contestnameと打ちます。
例えば、atcoder abc123と打てば、work/abc123がa.cppからf.cppまでできて、これらを編集していきます。

デバッグの時は、
ctrl+shift+Bでコンパイル
F5でinput.txtを入力したときのデバッグ
cptest aでa問題の自動テスト(本当はツールに自動提出機能があるため、ここで全問正解したら自動で提出ができるようにしたかったが、謎のエンコードエラーがでて実装できなかった)

大体こんな感じです。

また新しいコンテストを始めるときは、atcoder newcontestnameを打てばいいです。
そしたら、自動でabc123フォルダがord_sourceに格納されます。

VSCodeはworkspaceを開いて使用してください。
また、workspaceのフォルダを名は自動で取得するため、どんな名前でも構いません。

yudaiikenoya
競技プログラミングはじめました。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away