WSL2環境にてcargo competeでatcoderにログインする

環境

  • windows 11
  • visual studio code
  • WSL2
  • Rust

cargo competeとは?

  • cargo compete new abc300 とすると問題別のRustファイルを作ってくれて、テストケースもダウンロードしてくれる(下記画像)

  • cargo compete test a でa問題の全テストケースをチェックしてくれる
  • (cargo compete submit a で提出は、最近はできないと思う)
  • ojのような物です https://github.com/online-judge-tools/oj

cargo compete login atcoder に失敗(と、解決方法)

それでも提出はできない

  • すぐさま cargo compete submit a するも、error: Submission rejectedとなる
  • (そういえばojもいつからか自動提出はrejectされるようになってた記憶)
  • 提出はブラウザからコピペすることにしましょう

でもログインはしておいた方がいい

  • 「ログイン通すのは面倒そうだからやらなくていいか!」とはならない
  • abc300は過去のコンテストだからログインなしでテストケースダウンロードできるけど、開催中のコンテストはログインユーザーしかダウンロードできなかったはず
  • なので、開催中コンテストでcargo competeを使う人は、Cookieコピペのログインまで通しておかないと、本番で困ることになる
  • コンテスト前には cargo compete login atcoder と入力してログイン状態が維持できているか確認しておくと、さらに良い

2026/01/17 開催中コンテストで動作確認

  • ログイン済み
  • cargo compete new abc441✅
  • cargo compete test a✅
  • cargo compete submit a❌️

codingame (こどげ) Soak Overflow💦🤖Summer Challenge 2025 参加記 全280位 Gold

コンテストページ

私の結果

  • 280位 Gold🏆️
  • (Legendは166位まで)

感想

  • 166位までがLegendなので行きたかった
  • (途中、Gold 10位あたりのこともあった)
  • 参加者(提出者)3500人ほど

最終手法

  • MOVE全探索からの、攻撃は各エージェントで個別に評価関数からBest解を採用
  • 相手の行動をほぼ予想していない
    • 敵がボム持っていて、範囲内に味方がいたらそこに投げてくる予想、くらい

前半:LLM

  • 最初はGeminiにコーディングさせ、手を加えずに提出
  • 各エージェントごとにMOVE&攻撃を評価関数のBestで決定
  • ゲームの把握、試行錯誤に役立った👍
  • 欠点
    • ひっそりバグを埋め込む
    • コードが長くなる(最終1000行)
  • なので後半は手書きで、方針もコードも書き直し(最終655行)

後半:手書き

  • MOVE全探索 O(5^エージェント数)
    • とはいえ「動き回るとボムを避けれるかも」というのがあるので「停滞禁止」とした O(4^エージェント数)
  • MOVEが決まった状態で、各エージェントの攻撃は評価関数のBestで決める
  • 評価値 = MOVE評価値 + ∑(各エージェントの攻撃評価値)
  • これのBestを採用

コンテスト終了3日前?サイトが重い...

  • これくらいから皆が「時間いっぱい計算・探索させる」&「提出しまくり」になるのか、サイトが重くなる
  • 提出して様子を見ることが困難に
  • これにて撤退😭
  • ★知見:上記の理由により、終盤に全力出すよりも中盤でリードしておくほうがストレスが少なそう(次回やる)

Q.「自分の評価関数Botで相手の行動を予想できるのか?」

  • そうは思えなかった
  • 撃っては引く人もいるだろうし、フォーカスして1体を倒す人もいるだろうし、カバー重視の人もいるだろう
    • とはいうものの、皆はランキングが上がるように調整して提出するので傾向はあるはず
    • 自分の評価関数くらいしか予想の道具がない
    • 「自分の評価関数で相手を予想」それでいいらしい

評価関数ガチャで右往左往

  • 上位がLegendに行った後、私はGold内で10位あたりに居たこともあった
    • (とはいえ評価関数ガチャでの勝ち&運で想定以上に(割り振られた150戦でたまたま)勝ったのだろう)
    • BOSSに勝ててなかったので、近そうで遠い距離かも
  • 評価関数ガチャは知識を重ねている感じがしない😭

コンテスト後のタイムライン

ふまえて、やりたいこと

  • MCTS, DUCT, 聞いたことはある...🤔程度
  • 聞いたことがあるだけだと「今回の設定で適用できそうか?」判定できない
  • 次回に向けてthunderさんの本📕を買いました
    • 追記:読んだけど、取れる選択肢が多い場合にDUCTをどう使えばいいのか?など
    • 過去門とDUCTを実際に使っている人から学ぶ必要がありそう
  • bowwowさんの「ローカル自己対戦でパラメタ調整」は取り入れたい
  • simanさんの「claude codeにジャッジコードを読ませてルールの細かいところを聞くとソースコードの場所も教えてくれるので便利」
  • 自分の2手先など読む(評価したい)ならビムサ
    • (🤔相手も2回動くので盤面結構違うよね)
  • 相手の行動予想ならminimax (自分の評価関数使用)
    • 方針:1手読み。双方択を山登りで作って最後にminimax https://x.com/viewlagoon/status/1949782629588595096
    • (🤔相手の行動Best5が予想できたとして、それに対応するこちらの手も5種類決まるが、最終的にどれにする?)
  • 山登り:これを使えばMOVEと攻撃を混ぜて最適化できたかも

D - Home Garden セグ木で殴る

解説

code

#include <atcoder/lazysegtree>
using namespace atcoder; // 忘れがち

// 区間加算・区間和取得
struct S{
    long long value;
    int size;
};
using F = long long;

S op(S a, S b){ return {a.value+b.value, a.size+b.size}; }
S e(){ return {0, 0}; }
S mapping(F f, S x){ return {x.value + f*x.size, x.size}; }
F composition(F f, F g){ return f+g; }
F id(){ return 0; }

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);

    std::vector<S> v(200000+10, {0, 1});
    atcoder::lazy_segtree<S, op, e, F, mapping, composition, id> seg(v);

    // input
    ll Q;cin>>Q;
    ll plant_cnt=0;
    ll current_pos=0;
    while(Q--){
      ll ty;cin>>ty;

      if(ty==1){
        // うえる
        plant_cnt++;
      }
      else if(ty==2){
        // T日まつ
        ll T;cin>>T;
        seg.apply(0, plant_cnt, T); // 足す
      }
      else{
        // 収穫
        ll H;cin>>H;
        ll harvest_cnt=0;
        while(true){
          ll h = seg.prod(current_pos, current_pos+1).value;
          if(h>=H){
            harvest_cnt++;
            current_pos++;
          }else{
            break;
          }
        }
        p(harvest_cnt);
      }
    }

    return 0;
}

凶悪問題 abc379_c から学ぶ思い込みの怖さ😈

問題

思い込み1 : Nは200000以下

  • 今回の問題はN<=2e9
  • 初提出ではN<=2e5だと思い込んだコードを提出してWA & MLE
  • 長さNの配列確保でMLEするので気づきやすいが、Nがこんなに大きい問題は珍しい

思い込み2 : 位置Xはソートされている

  • これは私はひっかからなかったのだが、コンテスト後のタイムラインでは「Xはソートされてないのかよ!」というのを多数見た

思い込み3 : GPTの生成するコードはチェックする必要なし

  • これは私の解き方固有の問題ではあるが、GPTに「等差数列の和」を求める関数を作ってもらった
  • コードもチラッと見て問題ないことを確認したが、引数や戻り値がintなのが落とし穴で、何度もWAを出した
  • これはランダムテストケース生成では見つけづらい
  • intをlong longに書き換えて、ようやくACすることができた

AHC037 延長戦 天才貪欲 vs 近い葉マージ vs ビームサーチ

Links

結果

延長戦:天才貪欲の再現 (score : 5,388,249,433)👍️

  • 全頂点を葉としてマージしていく。優先度は、マージ後の点の(x+y)
  • これにより、右上からマージされていく
  • この点数が並んでいる(23~30位)ことにコンテスト中に気づければ、天才貪欲の存在を察知できる
  • この手法のすごいところ
    • 近い葉マージも自然と入る(遠い点のマージはx+yが低くなるので後回しになる)
    • マージが秩序立って行われる(右上から左下へ)
  • 提出(コメント付き)https://atcoder.jp/contests/ahc037/submissions/57828180
  • Seed 0の結果⏬️

延長戦:近い葉マージ (score : 3,496,296,312)😭

  • コンテスト中にやろうとしていたもの。しかしこれが完成していたとしても570位程のようだ
  • 全頂点を葉としてマージしていく。優先度は、2頂点のL1距離の小さい順
  • お気持ち:離れた点をマージしても、その点は使わなそう
  • なぜダメなのか?:クラスタができ、クラスタ間をマージする時に大きなコストがかかる
  • 提出(コメント付き)https://atcoder.jp/contests/ahc037/submissions/57828739
  • Seed 0の結果⏬️

惜しいノート

  • コンテスト中の考察ノート
  • 右上からマージしていき、その結果をさらにマージしていくアイデアはあった
  • ただ「マージした2点はもうマージに含めない(★)」というのが抜けていた
  • その結果「元の点がN点だと、マージで新しくできる点がN-1点で、4段くらいしか作れない...」と考えていた
  • ★のアイデアを使うと無駄な辺が減り、グリッドではなく木になる(下記画像の紫の太い線)

1位の解法

2024/09/19 追記:さらに延長戦!ビームサーチ (score : 5462997128)👍️

  • AHCラジオを見ていると「貪欲からビームサーチは自然」とか「こうやって枝刈りして」など見たのでビームサーチにトライ
  • ラジオではサラッと言われているけど、私の場合実装に1日かかった ^^;
  • 提出(本番2位相当) https://atcoder.jp/contests/ahc037/submissions/57911179
  • まずビーム幅1で貪欲と同じスコアが出るようにする
    • 枝刈りでミスして大変だった
    • ●枝刈りなしでビームサーチだけ完成させる
    • ●枝刈りを入れてスコアが変わらず速度UPのみすることを確認
    • と分けるべきだった。枝刈りなしだと重すぎて解が(手元でも)求まらない場合もありそう...
  • 次に、ビーム幅を増やすとStateのコピーが重いのでMiniStateを作って候補の時点では差分のみ持った
  • ビーム幅は70までいけた。wataさんの実装では2200
  • ビーム幅を増やしていくと今度はMLEが起こった。resize(0)では不足で、shrink_to_fit()してcapacityも解放させる必要があった。速度も上がった
  • ソート済み配列に1つ値を追加してまたソートする際、implace_mergeを使った。これも速くなった
  • 状態の重複除去について。ビームサーチは多様性が大事なのに、マージの順番が違うだけで同じ状態になりうるので、これは除去したい。「setでやるのか?重そう...」などいい方法が思いつかないのでwataさんの実装を見ると、(生きている)各頂点をハッシュ化してその和をハッシュ値としていた。ラジオでは触れられていなかったが、これは学びになった
fn f(p: (i32, i32)) -> i64 {
    (p.0 as i64 + 1) * 1000000007 + p.1 as i64 + 1
}
  • Seed 0の結果⏬️