Open4

Rustでのatcoder (cargo compete)メモ

どこかにコンテストやるフォルダを作成してinit

$ mkdir atcoder
$ cd atcoder
$ cargo compete init atcoder

compete.toml が作成されるのでカスタマイズする。

一旦、↓の感じ

compete.toml
# Path to the test file (Liquid template)
#
# Variables:
#
# - `manifest_dir`: Package directory
# - `contest`:      Contest ID (e.g. "abc100")
# - `bin_name`:     Name of a `bin` target (e.g. "abc100-a")
# - `bin_alias`:    "Alias" for a `bin` target defined in `pacakge.metadata.cargo-compete` (e.g. "a")
# - `problem`:      Alias for `bin_alias` (deprecated)
#
# Additional filters:
#
# - `kebabcase`: Convert to kebab case (by using the `heck` crate)
test-suite = "{{ manifest_dir }}/testcases/{{ bin_alias }}.yml"

# Open files with the command (`jq` command that outputs `string[] | string[][]`)
#
# VSCode:
#open = '[["code", "-a", .manifest_dir], ["code"] + (.paths | map([.src, .test_suite]) | flatten)]'
# Emacs:
#open = '["emacsclient", "-n"] + (.paths | map([.src, .test_suite]) | flatten)'

[template]
src = '''
#[allow(unused_imports)]
use itertools::Itertools;
#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_imports)]
use std::collections::{HashMap, HashSet, VecDeque};
#[allow(unused_imports)]
use std::f64::consts::PI;

fn main() {
    proconio::input! {
        n: usize,
        m: usize,
        a: [[i32; n]; m], // `a` is Vec<Vec<i32>>, (m, n)-matrix.
        string: String, // read as String
        chars: proconio::marker::Chars,   // read as Vec<char>
        bytes: proconio::marker::Bytes,   // read as Vec<u8>
    }
}

#[allow(dead_code)]
fn is_prime(n: usize) -> bool {
    if n < 2 {
        return false;
    }
    if n == 2 {
        return true;
    }
    let mut result = true;

    let s_root = (n as f64).sqrt() as usize;
    for i in 2..=s_root {
        if n % i == 0 {
            result = false;
            break;
        }
    }
    return result;
}

#[allow(dead_code)]
fn make_divitors(n: usize) -> Vec<usize> {
    let mut res = Vec::new();
    let s_root = (n as f64).sqrt() as usize;
    for i in 1..=s_root {
        if n % i == 0 {
            res.push(i);
            let div = n / i;
            if div != i {
                res.push(div);
            }
        }
    }
    res.sort();
    return res;
}

/// bfs(幅優先探索)
/// nodes内のfromからの各nodeの最短距離を返します。
/// 到達できない場合は-1が入っています。
#[allow(dead_code)]
pub fn bfs(from: usize, nodes: &Vec<Vec<usize>>) -> Vec<isize> {
    let node_num = nodes.len();
    let mut todo = VecDeque::new();
    let mut visited = vec![-1; node_num];

    todo.push_back(from);
    visited[from] = 0;

    while !todo.is_empty() {
        let visit_node = todo.pop_front().unwrap();
        let push_nodes = &nodes[visit_node];
        for n in push_nodes {
            // 訪れていないnodeだけをtodoに追加
            if visited[*n] != -1 {
                continue;
            }
            visited[*n] = visited[visit_node] + 1;
            todo.push_back(*n);
        }
    }
    return visited;
}

#[allow(dead_code)]
fn print_typename<T>(_: &T) {
    println!("type=<{}>", std::any::type_name::<T>());
}
'''

[template.new]
# `edition` for `Cargo.toml`.
edition = "2018"
# `profile` for `Cargo.toml`.
#
# By setting this, you can run tests with `opt-level=3` while enabling `debug-assertions` and `overflow-checks`.
#profile = '''
#[dev]
#opt-level = 3
#'''
dependencies = '''
proconio = "*"
itertools = "0.10.0"
'''
dev-dependencies = '''
#atcoder-202004-lock = { git = "https://github.com/qryxip/atcoder-202004-lock" }
'''

[template.new.copy-files]
"./template-cargo-lock.toml" = "Cargo.lock"

[new]
kind = "cargo-compete"
# Platform
#
# - atcoder
# - codeforces
# - yukicoder
platform = "atcoder"
# Path (Liquid template)
#
# Variables:
#
# - `contest`:      Contest ID. **May be nil**
# - `package_name`: Package name
path = "./{{ contest }}"

#[new]
#kind = "oj-api"
#url = "https://atcoder.jp/contests/{{ id }}"
#path = "./{{ contest }}"

# for Library-Checker
#[add]
#url = "https://judge.yosupo.jp/problem/{{ args[0] }}"
##is-contest = ["false"] # optional
##target-kind = "bin" # ["bin", "example"]. default to "bin"
#bin-name = '{{ args[0] }}'
##bin-alias = '{{ args[0] }}' # optional
##bin-src-path = './src/bin/{{ bin_alias }}.rs' # optional

# for yukicoder
#[add]
#url = '{% case args[0] %}{% when "contest" %}https://yukicoder.me/contests/{{ args[1] }}{% when "problem" %}https://yukicoder.me/problems/no/{{ args[1] }}{% endcase %}'
#is-contest = ["bash", "-c", '[[ $(cut -d / -f 4) == "contests" ]]'] # optional
##target-kind = "bin" # ["bin", "example"]. default to "bin"
#bin-name = '{% assign segments = url | split: "/" %}{{ segments[5] }}'
##bin-alias = '{% assign segments = url | split: "/" %}{{ segments[5] }}' # optional
##bin-src-path = './src/bin/{{ bin_alias }}.rs' # optional

[test]
# Toolchain for the test. (optional)
toolchain = ""
# Profile for `cargo build`. ("dev" | "release")
#
# Defaults to `"dev"`.
#profile = "dev"

#[submit.transpile]
#kind = "command"
#args = ["cargo", "equip", "--exclude-atcoder-crates", "--resolve-cfgs", "--remove", "docs", "--minify", "libs", "--rustfmt", "--check", "--bin", "{{ bin_name }}"]
##language_id = ""

TODO:

  • atcoder の snipet周りをvimのプラグインで整理する。
ログインするとコメントできます