😎

VSCodeでNimのAtCoder環境を構築

に公開

たとえCodonが使えようとも、同じくPythonライクで処理速度の速いAtCoderに最適な言語の1つNimの環境構築について、ご参考までに書いておきます。
※2025年10月18日から適用となった2025/10ジャッジアップデートに対応して、修正しました

環境の前提

  • Windows
  • WSL2
  • VSCode

皆さん、基本はC++やPythonなどを使っていて、完全にNimにスイッチするわけではないでしょう。
ぜひ、この機会にDockerの導入を検討ください。
コンテナごとに環境を持てて、非常に快適です。
VSCodeのdevcontainerでAtCoder環境を構築という記事も、あわせてご覧ください。

インストール(Dockerfile)

2025/10ジャッジアップデートの使用できる言語とライブラリの一覧内にあるNim2.2.4のインストールスクリプト通りにインストールすればいいわけで、ここではそれをubuntuにのせたDockerfileをあげておきます。
VSCodeでの使用を前提に、Nim Language Serverもインストール、もちろんDockerと、
みんな大好きonline-judge-tools(まだ、コンテスト中は使えますから…)も入れてあります。
(online-judge-toolsについては、このDockerfileを使ったVSCodeのdevcontainer内でsubmitしても、結果表示のブラウザが立ち上がらなかったので、submit.pyのshow resultのところのutils.webbrowser_register_explorer_exe()の行をコメントアウトして使っています。)

Dockerfile_AtCoder-Nim
FROM ubuntu:22.04

#AtCoder installation script
WORKDIR /tmp
RUN ln -sf /usr/share/zoneinfo/Etc/UTC /etc/localtime && bash -c 'echo Etc/UTC > /etc/timezone'
RUN apt update && apt install -y bzip2 curl xz-utils build-essential git 
RUN apt install -y lsb-release wget software-properties-common gnupg
RUN wget https://apt.llvm.org/llvm.sh
RUN chmod +x llvm.sh
RUN ./llvm.sh 20 all
RUN update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-20 1
RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-20 1
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3 1
ENV CHOOSENIM_CHOOSE_VERSION=2.2.4
RUN curl https://nim-lang.org/choosenim/init.sh -sSf | bash -s -- -y
ENV PATH=ENV PATH=/root/.nimble/bin:$PATH
RUN apt install libopenblas-dev liblapack-dev -y
RUN nimble install neo@0.3.5 -y
RUN nimble install https://github.com/zer0-star/Nim-ACL@0.1.0 -y
RUN apt install -y libgmp3-dev
RUN nimble install https://github.com/chaemon/bignum@1.0.6 -y
RUN nimble install https://github.com/nim-lang/bigints@#ca00f6da386af9ad7e3abf603c0201da6a014477 -y
RUN nimble install arraymancer@#84af537af1bc1f90229fff2b90abf5e5c1b02616 -y
RUN nimble install regex@0.26.3 -y
RUN nimble install nimsimd@1.3.2 -y
RUN nimble install https://github.com/nim-lang/sat@#faf1617f44d7632ee9601ebc13887644925dcc01 -y
RUN apt install -y python3-dev
RUN wget https://archives.boost.io/release/1.88.0/source/boost_1_88_0.tar.gz
RUN tar -xf boost_1_88_0.tar.gz
WORKDIR /tmp/boost_1_88_0
RUN ./bootstrap.sh --without-libraries=mpi,graph_parallel
RUN ./b2 install
RUN ldconfig
WORKDIR /tmp
RUN apt install -y libfftw3-dev
RUN wget https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
RUN tar -xvf eigen-3.4.0.tar.gz
WORKDIR /tmp/eigen-3.4.0
RUN cp -r Eigen/ unsupported/ /usr/local/include/
WORKDIR /tmp
RUN wget https://github.com/atcoder/ac-library/archive/refs/tags/v1.5.1.tar.gz
RUN tar -xvf v1.5.1.tar.gz
RUN cp -r ac-library-1.5.1/atcoder /usr/local/include
RUN apt install -y libmpfr-dev

# Nim Language Server 
RUN nimble install nimlangserver -y

# online-judge-tools
RUN apt install -y python3-pip &&\
    #pip3 install online-judge-tools
    pip3 install git+https://github.com/sukenori/oj.git

# Docker
RUN apt install -y docker.io

参考①(devcontainer.json)

あくまで、VSCodeのdevcontainerでAtCoder環境を構築の通りのディレクトリ構造にしたら、こうなりますよ、という参考として挙げておきます。
copilotはコンテスト中は使えません

devcontainer.json
{
  "name": "AtCoder-Nim",
  "build": {
    "dockerfile": "Dockerfile_AtCoder-Nim"
  },
  "workspceMount": "source=C:/Users/ユーザー名/OneDrive/Development/Competitive_Programming/Workspaces/AtCoder/AtCoder-Nim,target=/workspaces/AtCoder-Nim,type=bind",
  "workspaceFolder": "/workspaces/AtCoder-Nim",
  "mounts": [
    "source=C:/Users/ユーザー名/OneDrive/Development/Competitive_Programming/Solved_Code,target=/workspaces/Solved_Code,type=bind",
    "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
  ],
  "customizations": {
    "vscode": {
      "extensions": [
        "NimLang.nimlang",
        "vadimcn.vscode-lldb",
        "GitHub.copilot",
        "GitHub.copilot-chat",
        "ms-azuretools.vscode-docker"
      ]
    }
  },
  "postCreateCommand": "./.devcontainer/postCreateCommand.sh"
}

参考②(postCreateCommand.sh)

文字通り、コンテナクリエイト後に走るスクリプトですので、(ojのログインなんかをしていました)
2025年の言語アップデートでは、Nimは2.2.4ですので、将来のためにchoosenim 2.2.4としてダウングレードしておいてもいいと思います。

postCreateCommand.sh
#!/bin/bash
RUN choosenim 2.2.4
oj login -u ログイン名 -p パスワード https://atcoder.jp/

参考③(.code-workspace)

さっきマウントしておいたディレクトリで、ワークスペースを構成します。
(提出コード集部分は一例です。)
コンテストが終わったら、.Contesutから中身を移していったりします。

AtCoder-Nim.code-workspace
{
	"folders": [
		{
			"name": "AtCoder-Nim",
			"path": "/workspaces/AtCoder-Nim"
		},
		{
			"name": "AtCoder_Beginner_Contest",
			"path": "/workspaces/Solved_Code/AtCoder/AtCoder_Beginner_Contest"
		},
		{
			"name": "AtCoder_Regular_Contest",
			"path": "/workspaces/Solved_Code/AtCoder/AtCoder_Regular_Contest"
		},
		{
			"name": "AtCoder_Grand_Contest",
			"path": "/workspaces/Solved_Code/AtCoder/AtCoder_Grand_Contest"
		},
		{
			"name": "ABC_Like_Contest",
			"path": "/workspaces/Solved_Code/AtCoder/ABC_Like_Contest"
		},
		{
			"name": "ARC_Like_Contest",
			"path": "/workspaces/Solved_Code/AtCoder/ARC_Like_Contest"
		}
	],
	"settings": {
		"terminal.integrated.env.linux": {
			"PATH": "${env:PATH}:/workspaces/AtCoder/.workspaces/Nim"
		}
	}
}

tasks.json

ojの自動化を導入するので、コンパイル、テストのダウンロード、テスト、提出の各taskを用意します。
コンパイルオプションも、Nim2.2.4のインストールスクリプトに揃えます。
コンパイルをデフォルトのタスクにして、提出のタスクにショーカットをつければ、その2つのショートカットでほぼほぼCLI要らずになります。というのも、提出のタスクは、testディレクトリの削除→サンプルケースのダウンロード→テスト→提出のコンボにしてあるからです。URL渡しは、サンプルケースのダウンロード時に、出てくるウィンドウに問題文URLをコピペするだけです。

tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "type": "shell",
            "command": "${userHome}/.nimble/bin/nim",
            "args": [
                "cpp",
                "-d:release",
                "--opt:speed",
                "--multimethods:on",
                "--warning[SmallLshouldNotBeUsed]:off",
                "--hints:off",
                "--maxLoopIterationsVM:10000000000000",
                "--maxCallDepthVM:10000000000000",
                "-g",
                "-o:a.out",
                "${file}"
            ],
            "presentation": {
                "panel": "shared"
            }
        },
        {
            "label": "remove test",
            "type": "shell",
            "command": "rm",
            "args": [
                "-rf",
                "${workspaceFolder}/test"
            ],
            "presentation": {
                "panel": "shared"
            }
        },
        {
            "label": "download test",
            "type": "shell",
            "command": "oj",
            "args": [
                "d",
                "${input:url}",
                "-d",
                "${workspaceFolder}/test",
                "-s"
            ],
            "presentation": {
                "panel": "shared",
                "showReuseMessage": false
            },
            "dependsOn": ["remove test"],
            "dependsOrder": "sequence"
        },
        {
            "label": "test",
            "type": "shell",
            "command": "oj",
            "args": [
                "t",
                "-c",
                "${workspaceFolder}/a.out",
                "-d",
                "${workspaceFolder}/test/"
            ],
            "presentation": {
                "panel": "shared"
            }
        },
        {
            "label": "submit",
            "type": "shell",
            "command": "oj",
            "args": [
                "s",
                "${input:url}",
                "${file}",
                "-w",
                "0",
                "-y"
            ],
            "presentation": {
                "panel": "shared"
            },
            "dependsOn": ["build","download test","test"],
            "dependsOrder": "sequence"
        },
    ],
    "inputs": [
        {
            "type":"promptString",
            "id":"url",
            "description": "URL of the task"
        }
    ]
}

launch.json

これでデバッグは動きはしますが、変数はすこぶる見辛いですし、あまりいい使用感ではないですね…

launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "lldb debug",
            "type": "lldb",
            "request": "launch",
            "preLaunchTask": "build",
            "program": "${workspaceFolder}/a.out",
            "args": ["<", "${workspaceFolder}/test/sample-1.in"],       
            "cwd": "${workspaceFolder}"
        }
    ]
}

尊敬する優秀なNim使いの皆さんによって、Nim-ACLも整備され、非常に快適な環境が整えられています。
それだけに、後は、実力だけなんですよね…

Discussion