hotaruの蛍雪日記

競プロとゲームをしています

皆さんは競プロをするときにエディタのスニペット機能を使っていますか?私のスニペットを見せます。

f:id:hotarunx:20201026234657g:plain
using snippet

皆さんは競プロをするときにエディタのスニペット機能を使っていますか? 私のスニペットを見せます。 言語はC++、エディタはVSCodeです。

out

cout << ans << "\n";
cout << ans << ans << "\n";
"out": {
    "body": "cout << ${1:ans} << \"\\n\";",
    "prefix": "out"
},
"out2": {
    "body": [
        "cout << ${1:ans} << ${2:ans} << \"\\n\";"
    ],
    "description": "out2",
    "prefix": "out2"
},

値を標準出力する。 使用率はダントツで1位です。

YesNo

cout << (ans ? "Yes" : "No") << "\n";
"yesno": {
    "body": [
        "cout << (${1:ans} ? ${2|\"Yes\" : \"No\",\"YES\" : \"NO\",\"yes\" : \"no\"|}) << \"\\n\";"
    ],
    "description": "yesno",
    "prefix": "yesno"
}

YesかNoを出力する。 AtCodercase-sensitiveなのでいくつか選べるようにした。

コンテナをスペース区切りで出力

for (auto i = vec.begin(); i != vec.end(); i++) {
    cout << *i << (i != vec.end() - 1 ? ' ' : '\n');
}
"output container separated by spaces": {
    "body": [
        "for (auto ${1:i} = ${2:vec}.begin(); ${1:i} != ${2:vec}.end(); ${1:i}++) {",
        "    cout << *${1:i} << (${1:i} != ${2:vec}.end() - 1 ? ' ' : '\\n');",
        "}",
        "$0"
    ],
    "description": "output container separated by spaces",
    "prefix": "outspaces"
},

コンテナの値を順にスペース区切りで出力して最後は改行する。 for内の条件演算子は速度に悪いが問題ないだろう。

all

a.begin(), a.end()
"all": {
    "body": "$1.begin(), $1.end()$0",
    "prefix": "all"
},

コンテナのメンバ関数beginendを同時に書く。 sort, lower_boundなどで使う。

max

max_hoge = max(hoge_i, max_hoge);
"max": {
    "body": [
        "${1:max_hoge} = max(${2:hoge_i}, $1);"
    ],
    "description": "max",
    "prefix": "max"
},

最大値max_hogehoge_iで更新する。 minもある。

cumulative_sum

vector<int> csv(n + 1);
csv[0] = 0;
for (int i = 0; i < n; i++)
    csv[i + 1] = csv[i] + v[i];
"cumulative_sum": {
    "body": [
        "vector<int> cs${1:a}(${2:n} + 1);",
        "cs${1:a}[0] = 0;",
        "for (int i = 0; i < ${2:n}; i++)",
        "    cs${1:a}[i + 1] = cs${1:a}[i] + ${1:a}[i];",
        "$0"
    ],
    "description": "cumulative_sum",
    "prefix": "cumulative_sum"
},

累積和をさっと書く。

input vector

vector<int> a(n);
for (int i = 0; i < n; i++) cin >> a[i];
"inputvec": {
    "body": [
        "vector<${1:int}> ${2:a}(${3:n});",
        "for (int i = 0; i < $3; i++) cin >> $2[i];",
        ""
    ],
    "description": "inputvec",
    "prefix": "inputvec"
},

標準入力から配列を受け取る。 型・変数名・配列長はコーディング時に入力できる。 ほかにも標準入力スニペットはいくつか用意している。

inf

constexpr int INF = 1000000000 + 8;
"inf": {
    "body": [
        "constexpr int INF = 1000000000 + 8;"
    ],
    "description": "inf",
    "prefix": "inf"
},

テンプレを短くしたいのでINFとかもテンプレからスニペットに移しました。

ceil

constexpr int ceil(long long a, long long b) { return (a + b - 1) / b; }
"ceil": {
    "body": [
        "constexpr int ceil(long long a, long long b) { return (a + b - 1) / b; }"
    ],
    "description": "ceil",
    "prefix": "ceil"
},

整数を切り上げて割り算する関数。 たまに使う関数はテンプレではなくスニペットに移しました。

log2n

constexpr long long log2n(long long n) {
    long long log_n = 1;
    while ((1LL << log_n) < n) log_n++;
    return log_n;
}
"log2n": {
    "body": [
        "constexpr long long log2n(long long n) {",
        "    long long log_n = 1;",
        "    while ((1LL << log_n) < n) log_n++;",
        "    return log_n;",
        "}",
        ""
    ],
    "description": "log2n",
    "prefix": "log2n"
},

floor(\log_2n)を返す関数。 このコードはよく見るので関数化してスニペットに入れた。 多分あってる。

めぐる式二分探索

// めぐる式二分探索
// (ng, ok] or [ok, ng)
// 条件を満たす最小(最大)のindex okと
// 条件を満たさない最大(最小)のindex ngを探索する
int ok = n;  // 条件を満たすindex
int ng = -1;   // 条件を満たさないindex
while (abs(ok - ng) > 1) {
    int mid = (ok + ng) / 2;
    if (isSatisfy(mid))
        ok = mid;
    else
        ng = mid;
}
"meguru_binary_search": {
    "body": [
        "    // めぐる式二分探索",
        "    // (ng, ok] or [ok, ng)",
        "    // 条件を満たす最小(最大)のindex okと",
        "    // 条件を満たさない最大(最小)のindex ngを探索する",
        "    int ok = ${1:n};  // 条件を満たすindex",
        "    int ng = ${2:-1};   // 条件を満たさないindex",
        "    while (abs(ok - ng) > 1) {",
        "        int mid = (ok + ng) / 2;",
        "        if (${3:isSatisfy}(mid))",
        "            ok = mid;",
        "        else",
        "            ng = mid;",
        "    }",
        ""
    ],
    "description": "meguru_binary_search",
    "prefix": "meguru_binary_search"
},

めぐる式二分探索です。

感想

outなど入出力のスニペットは非常に便利だと思います。 それ以外はたまに書くコードの置き場になっている。

リンク