Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What are the problem?

Xcodeで競技プログラミング

これはCompetitive Programming (1) Advent Calendar 2020の8日目の記事です。

AtCoder Tools for Swift

SwiftでAtCoderを楽しむ方が増えてきたので、kyuridenamidaさん作のAtCoder ToolsをSwift対応させてみました。主にSwift環境について記述しますが、後半でC++の場合についても説明します。

  • AtCoder Tools Swift対応版
    swift branchにあります。本家にもマージされていますが、こちらには追加のサンプルなどが入っています。

  • AtCoder Tools Xcode対応版
    xcode branchにあります。上記のswiftブランチに加えてC++用のサンプルが含まれています。

AtCoder Toolsというのは、AtCoderから問題文やサンプルを取得して、ローカルテストや提出までできる超便利ツールです。
詳しくは「便利! AtCoder で競技プログラミングをするときに重宝する AtCoder Tools のご紹介」などを読んでみてください。

インストール方法

バージョン3.6以上のPythonが必要です。本家のAtCoder Toolsはpipでインストール可能ですが、上記の開発版をインストールするにはpoetryもインストールしておく必要があります。以下の手順でインストールできます。

$ cd (適当な作業ディレクトリを作ってそこに移動する)
$ git clone https://github.com/firewood/atcoder-tools.git
$ cd atcoder-tools
$ git checkout swift      # C++の方は xcode
$ poetry install

オプション省略時には、設定ファイルを~/.atcodertools.tomlとして作成する必要があります。workspace_dirの指定は必須です。
swiftブランチでは examples/swift/config.toml に以下のような設定ファイルを用意してあります。

examples/swift/config.toml
[codestyle]
#indent_type='tab'
indent_type='space'    # 区切り文字はスペース (default)
#indent_width=4        # インデント幅は4 (default)
#workspace_dir='~/temp/atcoder-tools/examples/swift'
workspace_dir='.'
#lang='python'
lang='swift'
code_generator_toml='./codegen.toml'    # コードジェネレータの指定、おそらく変更する必要はない
template_file='./template.swift'        # コードテンプレートファイルの指定

コードジェネレータを指定することで、(浮動小数点の変数の型を変更したりなど)かなり細かいカスタマイズをすることができますが、カスタマイズしたい場合はそれほどないと思います。
コードテンプレートファイルのほうは、自前のライブラリ関数などを追加していくことになると思います。
無指定時のテンプレートファイルはこれです。template_fileで指定できます。

コンテストデータの取得

コマンドラインから atcoder-tools gen abc200 のように呼び出すと、コンテストデータを取得し、workspace_dirの下のコンテスト名のディレクトリ(例えば abc200 )が作成されます。そこに問題毎のA B C D E Fのようなディレクトリが作成され、それぞれのディレクトリの下にmain.swiftが生成されます。
swift ブランチでは examples/swift/gen.sh にシェルスクリプトを用意してあります。
このシェルスクリプトでは gen コマンドを呼び出したあと、project_files にあるプロジェクトファイルをコンテスト名のディレクトリにコピーします。

$ cd examples/swift
$ ./gen.sh abc200

Xcodeで編集する

Xcodeで編集するにはCommand Line Toolのプロジェクトを作成する必要があります。
上記の gen.sh では abc200/A/ProblemA.xcodeproj が生成されるようになっています。

$ cd abc200/A
$ xed .

のようにしてプロジェクトを開くと、以下のように、パラメータの入力部分を含んだmain.swiftが自動生成されているはずです。(問題によっては解析に失敗することもあり、その場合はmain関数だけが生成されます)
あとはsolve関数の中身を埋めるだけになっています。

main.swift
import Foundation


func solve(_ N:Int) {
    var ans = 0

    print(ans)
}

func main() {
    var tokenIndex = 0, tokenBuffer = [String]()
    func readString() -> String {
        if tokenIndex >= tokenBuffer.count {
            tokenIndex = 0
            tokenBuffer = readLine()!.split(separator: " ").map { String($0) }
        }
        defer { tokenIndex += 1 }
        return tokenBuffer[tokenIndex]
    }
    func readInt() -> Int { Int(readString())! }
    func readDouble() -> Double { Double(readString())! }
    let N = readInt()
    _ = solve(N)
}

#if DEBUG
let caseNumber = 1
_ = freopen("in_\(caseNumber).txt", "r", stdin)
#endif

main()

Xcodeでデバッグする

AtCoderのように標準入力を前提とするプログラムをデバッグするときは、Xcodeのコンソールに入力を貼りつける必要があります。ただ毎回手入力したくないので、ローカル環境で試すときには、AtCoder Toolsで取得したテストケースのファイルを標準入力にリダイレクトするようにしてみました。(上のコードのfreopen)
これにより手元(DEBUG定義時)ではファイルから、提出時には標準入力から入力できます。提出時にファイルを書き換えたりする必要もありません。caseNumberを変えれば任意のテストケースでデバッグできます。
これを行うためにはデバッグ時のカレントディレクトリを入力ファイルのあるディレクトリにしておく必要があります。Product -> Scheme -> Edit Scheme... から変更できます。たとえば$(PROJECT_DIR)とするとプロジェクトのディレクトリにできます。そうするとプロジェクトファイルをコピーしたときでも使えます。(swift ブランチのサンプルではこの状態になっています)

workdir.png

実行すると、キーボード入力を待たずに結果が出力され、プログラムが終了するはずです。

result.png

XcodeのバージョンによってはDEBUGが未定義かもしれません。その場合はプロジェクトのBuild SettingsのSwift Compiler - Custom FlagsのActive Compilation ConditionsのDebugのところにDEBUGを追加します。(下図)

debug.png

まとめてテスト&提出する

Atcoder Toolsのtestコマンドにより、全てのサンプルでテストできます。これは例えばこういう感じのMakefileを用意しておくといいと思います。(サンプルにあります)

Makefile

.PHONY: test submit resubmit

test: build
    atcoder-tools test

submit: build
    atcoder-tools submit

resubmit: build
    atcoder-tools submit -u

build: a.out

a.out: main.swift
    swiftc $< -o $@

この例だとmakemake testは同じで、全てのサンプルをテストします。

ac.png

大丈夫そうであればmake submitで提出できます。テストが通らないと提出できませんが、テストケースと完全一致しない場合もあるので、そういうときは手動でコピー&ペーストして提出してください。
make resubmitで再提出可能です。

C++の場合

ほぼSwiftと同じです。xcodeブランチexamples/cpp/以下にプロジェクトファイルのサンプルがあります。
このサンプルを試すには、AtCoder Library/usr/local/include以下にインストールしてください。(つまり/usr/local/include/atcoder/modintなどが存在する状態)

おわりに

私は普段もっぱらC++でコンテストに参加していますが、これからはSwiftでも復習していきたいなと思っています。不具合や改善点などあれば、コメント欄やTwitterでぜひ教えていただきたいです。
Xcodeで楽しいAtCoderライフを送りましょう!

宣伝

競技プログラミングのコンテストカレンダーを作っていますのでよかったらご利用ください。主に短時間のコンテストを載せています。
自分のGoogle Calendarに追加することもできます。
https://competitiveprogramming.info/calendar

Swiftでの競技プログラミングで役立つ記事

編集履歴

  • 2021-05-03: Swiftブランチが本家に取り込まれたため、記述を更新
  • 2021-10-01: 生成されるディレクトリ名をツールの標準の方法にして、gen.shを整えた
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
8
Help us understand the problem. What are the problem?