LoginSignup
1
0

More than 1 year has passed since last update.

AHCのツールについて 第三回 ツール実行方法 (Ubuntu, unix, WSL)

Last updated at Posted at 2023-04-04

自己紹介

(ほとんどの人が)初めまして
uetaと申します。
電気機械系の大学院2年で研究はなぜか統計系統のことをやっています。

今回の目的

競技プログラミング特にAtcoderというサイトで提供されるツールの使用方法を説明します。
本サイトではマラソン系のコンテストはAtcoder heuristic Contest、通称AHCと呼ばれています。

今回はこちらで提供されるツールを Unix系(Ubuntu,centOS...)WSLで使うときの使用方法です。

割と新しいコンテストだと
以下のようにツールが与えられます。

Screenshot 2022-12-15 232120.png

これです。

構成

第一回 ビジュアライザについて
第二回 Windowsでの実行方法
第三回 Ubuntu, WSLでの実行方法   ←今回

今回の流れ

  1. 前提知識・このツールでできること
  2. 実行する手順(1.rustダウンロード, 2.ツールのダウンロード, 3.実行コマンド)

前提知識・このツールでできること

前提知識

  • ターミナル  ←存在が分かればいい
  • パスの概念  ←ファイル構造やコマンドを用いた移動ができる必要があり

このツールでできること

・ファイルの実行
・得点の算出
・実行ファイルの可視化
・入力値の生成

ここではインタラクティブとアウトプットオンリーと分けて考えています。
(アウトプットオンリーって名前が正しいのかは要相談)

実行する手順

1. rustをダウンロードする

rustを入れていない場合(cargoコマンドがないよと言われたとき)

rustの入れ方
# Ubuntu
sudo apt install rustc
# centos
sudo yum install rust-toolset

(ソース)https://news.mynavi.jp/techplus/article/rust-8/

うまくいかないときは以下参考

これで実行できるようになります。

2. AtCoderのコンテストサイトからツールをダウンロード

ローカル版 を選択しダウンロードします

下にローカル版よりダウンロードした場合のエクスプローラです。

各自の展開したい場所に展開するか、展開後に移動させてください。
まずは、展開(Extract all) します。

そのあと、README.html を開いてもらうと使い方を確認できます。
(初めに英語ができて、あきらめかけますが下に行くと日本語版があります。)

3. 実行コマンド

想定ファイル構造
━tools━in━0001.txt
    ┃ ┗0002.txt ...
    ┠src(ここは手を付けない)
    ┠target(ここは手を付けない)
    ┠cargo.toml(ここは手を付けない)
    ┠cargo.lock(ここは手を付けない)
    ┠README.html(手順書が書いてある)
    ┠seeds.txt
__________以下は実行用ファイルと実行時に生成されるファイル______
    ┠output━0001.txt
       ┗0002.txt ...
    ┠score━0001.txt
       ┗0002.txt ...
     ┠score.sh  ←これが100個まとめた時の実行用シェル
     ┠a.py   ←pythonで実行するときの実行ファイル
     ┗a.cpp   ←c++で実行するときの実行ファイル

上のようにファイルを作るように考えています
基本的には以上のファイル構造でtoolsの中に移動して実行する必要があります。

詳しくはREADMEに書かれているためので読みましょう
以下の内容はREADMEの内容を要約したものがメインです。
また、exですべてをまとめて実行できるようにしたものが書かれています。

入力ファイルの生成

seeds.txtに書き込んだ番号の入力値が生成されます。
実行時にtoolsの中までディレクトリを移動する必要があります。

入力ファイルの生成
#ディレクトリを移動します(各自環境が合うように変更してください)
cd C:\Users\ueta\Documents\qiita\202212\tools

cargo run --release --bin gen seeds.txt

・インタラクティブ型の実行例

インタラクティブ(AHC16)の時の想定です

以下では実行コードを同じツール内に置くことを想定しています。
別の場所にしたい場合は相対パス等を勉強して書き直すとよいと思います。

ターミナルより以下のように実行します。

aというファイルを実行するとき
#ディレクトリを移動します(各自環境が合うように変更してください)
cd C:\Users\ueta\Documents\qiita\202212\tools

#testerの部分はvisに変わったりもするので要読README
## pythonの実行
cargo run --release --bin tester python a.py < in/0000.txt > out.txt

## c++の実行
g++ -o ./a ./a.cpp
cargo run --release --bin tester ./a < in/0000.txt > out.txt

コンテストによっては条件を指定できることがあるのでREADME参照

ex1. 100個をまとめて実行

100個まとめて実行する場合はそれなりに工夫が必要である。
以下のコードをコピペして、(.sh)として保存する。

インタラクティブの時の100個の実行.sh
#各自パスの変更が必要
cd /home/ueta/atcoder/contest/tools

#コンパイル(c++の時のみ) ファイルの場所は変更してください。
g++ -o ./a ./a.cpp
#フォルダを作る
mkdir -p output score

#何番から何番まで?
start=0;last=99;

ans=0;
for d in `seq ${start} ${last}`;
do
    j=$(printf "%04d\n" "${d}")
    ##ここに実行コマンドを置く(以下はc++) ファイルの場所は注意
    cargo run --release --bin tester ./a < ./in/${j}.txt  >./output/${j}.txt 2> ./score/${j}.txt
    ##
    # "Score = " より後の文字列を抽出する(この部分は変わる可能性あり)
    var=$(grep "Score = " ./score/${j}.txt | sed -e 's/[^0-9]//g')
    ans=$(($ans+$var))
    echo $j $var;
done
ans=$(($ans/($last-$start+1)))
echo "Average Score" $ans;

これは以下のようにして実行できる

./test100.sh

すると1回で100個を回すことができ、その平均値を算出できる。

0000 1400
0001 1800
0002 1100
0003 1800
...
0095 1500
0096 1600
0097 1600
0098 1400
0099 1500
Average number 1461

また、100では偏りが出るため500回、数千回で算出するといいらしい。(要文献)
(相対評価の時はlogにするといいともいわれている 参考: https://twitter.com/kiri8128/status/1629874801040031744

ex2. 並列実行用の設定

以下のコードで並列化ができる。
しかし、実行環境の計算能力を超えることはできないため、
並列しすぎるとそれぞれの計算能力が落ちることには注意が必要。

そのため、自分は parallelを導入することで高速化しました。

# Ubuntu
sudo apt install parallel
# centOS
sudo yum -y install parallel

ダウンロードした後は以下のコードで並列実行ができるようになる。

インタラクティブの時の並列実行.sh
#各自パスの変更が必要
cd /home/ueta/atcoder/contest/tools

#コンパイル
g++ -o ./a ./a.cpp
#フォルダを作る
mkdir -p output score

#何番から何番まで?
start=0;last=99;
#何個並列するか
para=20

seq ${start} ${last} | parallel --no-notice -j ${para} '
    j=$(printf "%04d\n" "{}")
    cargo run --release --bin tester ./in/${j}.txt >./output/${j}.txt 2>./score/${j}.txt
    var=$(grep "Score = " ./score/${j}.txt | sed -e 's/[^0-9]//g')
    echo $j $var;'

ans=0;
for d in `seq ${start} ${last}`;
do
    j=$(printf "%04d\n" "${d}")
    var=$(grep "Score = " ./score/${j}.txt | sed -e 's/[^0-9]//g')
    ans=$(($ans+$var))
done
ans=$(($ans/($last-$start+1)))
echo "Average Score" $ans;

・アウトプットオンリーの時の例

アウトプットオンリー(AHC17)の想定です。

インタラクティブ型ではなかった場合の例を示します。

アウトプットオンリー時は

  1. 実行して「in.txt」入力して「out.txt」を生成する
  2. ファイルをローカルテスタにかける(点数計算,ヴィジュアライズ)

という手順をとる

aというファイルを実行するとき
#ディレクトリを移動します(各自環境が合うように変更してください)
cd C:\Users\ueta\Documents\qiita\202212\tools

##コードの実行
#c++の実行コマンド
g++ -o ./a ./a.cpp
./a < in/0000.txt > out.txt

#python の実行コマンド
python a.py < in/0000.txt > out.txt

#結果の図示と得点計算
cargo run --release --bin vis in/0000.txt out.txt

並列実行で高速化

# Ubuntu
sudo apt install parallel
# centOS
sudo yum -y install parallel
test100_parallel.sh
#各自パスの変更が必要
cd /home/ueta/atcoder/contest/tools

#コンパイル(c++の時のみ)
g++ -o ./a ./a.cpp

#フォルダを作る
mkdir -p output score score2
#何番から何番まで?
start=0;last=99;
#何個並列するか
para=20

seq ${start} ${last} | parallel --no-notice -j ${para} '
    j=$(printf "%04d\n" "{}")
    ./a <./in/${j}.txt >./output/${j}.txt
    cargo run --release --bin vis ./in/${j}.txt ./output/${j}.txt >./score/${j}.txt 2>./score2/${j}.txt
    var=$(grep "Score = " ./score2/${j}.txt | sed -e 's/[^0-9]//g')
    echo $j $var;'

ans=0
for d in `seq ${start} ${last}`
do
    j=$(printf "%04d\n" "${d}")
    var=$(grep "Score = " ./score2/${j}.txt | sed -e 's/[^0-9]//g')
    ans=$(($ans+$var))
done
ans=$(($ans/($last-$start+1)))
echo "Average Score" $ans

最大100個並列処理し、結果をtxtに出力し、その結果の平均値を算出する仕組みになっています。
これで高速で全パターン試せます。

まとめ

これで全編終わりました。
ご覧いただきありがとうございました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0