趣旨
- 背景 : あんまり多くの入力に対してテストをしていないので、たくさんテストをして傾向をつかめるようにしていきたい
- そのためのやること整理と調べ物結果を、自分にメモを残す
- せっかくなので、学びとして共有する
- ちょっとずつ拡張して、いろんな考察ができるようにしていく
環境
- Windows
- VSCode も使っている
- プログラミング言語は C++。Python も使っている。
- C++ でコンパイルされた実行ファイルを
a.exe
とする
- C++ でコンパイルされた実行ファイルを
フォルダ構成
- 自作した AHC の解答コードは ./AHC というフォルダにまとめておく
- 入力ファイルが1つ=中身を毎回書き換えてつかう場合は in.txt にする。その時の出力ファイルは out.txt
- 入力ファイルを複数準備したときには ./in フォルダにまとめておく。その時の出力ファイルは ./out フォルダにまとめておく
- ファイル名は seed の番号がついたもの 0000.txt とか
本編
まずは1ファイルだけ動かす
AHCに参加している人なら、追加の情報量がない部分。ただ実行します。
a.exe < in.txt > out.txt
ここまでやって、Web 版のビジュアライザにコピペするのが現在のやり方。
VSCode のタスク登録(参考)
うえのコマンドもタスクに登録しておいたほうが無難か。そこまで長くはないが。。。
- 自分の環境では決まったフォルダに実行ファイルが
a.exe
で吐き出されるようにしてある - 入力ファイルと出力ファイルの場所指定は、作っているプログラムと同じ階層が指定されるようにして、タスクを走らせるので、こういう設定にしています。
- command のみを抜き出しています
"command": "D:[ここは各環境で]/a.exe < ${fileDirname}\\in.txt > ${fileDirname}\\out.txt",
スコアチェック(と最終結果の表示を)をローカルで実行する
AHC の大会では、Rust で書かれたチェッカーがある。ただ、山登りということで、ここではこれを Windows 環境用にコンパイル済みのものを使う
Windows 用にコンパイルされたチェッカの準備
- AHC の問題サイトにリンクがあるので、そこからダウンロード zip
- zip の解凍
- 中に vis.exe があり、これが本体
- AHC フォルダにまとめる
> vis.exe in.txt out.txt
すると、こんな感じで出る。例は AHC043 より
> Score = 508988
一緒に vis.html も出力される(ビジュアライズした結果)
複数ファイルに対応する伏線
複数の入力ファイルをまとめて処理する伏線として、入力ファイルを ./in フォルダに入れる。このときに処理する入力ファイルが 0000.txt だとすれば
> a.exe < ./in/0000.txt > ./out/0000.txt
> vis.exe ./in/0000.txt ./out/0000.txt
ちなみに、AHC の配布ファイルに gen.exe という、入力ファイル生成のプログラムがついてくる。これを(seeds.txt ファイルを使って)実行すると ./in フォルダに入力ファイルが生成される(詳細略。同梱の Readme.html を参照)
複数のスコアチェック(と最終結果の表示を)をローカルで実行する
さて、複数かけたい。 vis.exe を全ファイル手打ちは面倒なので(当たり前)、これをバッチファイルで処理する。
@echo off
for %%f in (./in/*.txt) do (
echo filename = ./in/%%f
a.exe < ./in/%%f > ./out/%%f
)
@echo off
for %%f in (./in/*.txt) do (
vis.exe ./in/%%f ./out/%%f
)
バッチファイルで for で回しているだけです。
Score = 533112
Score = 633150
Score = 597458
Score = 3711202
Score = 268420
Score = 100891
Score = 295299
Score = 5422760
Score = 7876622
Score = 43085
入力結果を別ファイルに放り込む
-
>
は元の内容に上書きしてしまうので>>
を使用 - ただ、一旦クリアしないといけないので
type nul > result.txt
をついか
@echo off
type nul > ./result.txt
for %%f in (./in/*.txt) do (
vis.exe ./in/%%f ./out/%%f >> ./result.txt
)
複数のスコアチェックと平均値を管理する
多くの入力で試すと、効果が出るケースと出ないケースの考察がしたくなります。また、全体としてどうなのか、という評価もしたくなります。
- vis.exe で出力されるものは
Score = 533112
という文字列しか出てこない。これは扱いづらい。 - そのため、数字だけ欲しくなる
スコアの数値だけを取り出す
- Rust のプログラムをいじる、という手段もあるし
- 得意なプログラミング言語で
vis.exe ./in/xxxx.txt ./out/xxxx.txt
の実行を回して取り出す、という手段もある。 - でも、もうしばらく、bat ファイルでやり切ります
bat ファイルでの取り出し (AHC043の場合)
- 出力されるのは
Score = ###
の形なのでfor
で切り出すfor /F "tokens=3" %%i in ('vis.exe ./in/%%f ./out/%%f') do set var=%%i
各ファイルの計算結果出力と合計の処理
- このとき、echo での値表示に際して、「環境変数の遅延評価」を設定しておかないと、値が正しく出てこない
setlocal enabledelayexpansion
- 変数の表示に
%
ではなく!
を使う
- ファイル名と値を一覧にして取り出すだけなら、ここまでで十分
- 平均計算をさせるために、
set /a
で数値計算を追加
@echo off
type nul > ./result.txt
setlocal enabledelayedexpansion
set sum=0
set count=0
for %%f in (./in/*.txt) do (
set /a count+=1
for /F "tokens=3" %%i in ('vis.exe ./in/%%f ./out/%%f') do set var=%%i
set /a sum=sum+var
echo %%f !var! >> ./result.txt
)
set /a sum/=count
echo !sum! >> ./result.txt
だいぶ、長ったらしくなりましたが、これで各ファイルの値を記録しつつ、平均スコアも出せる。
複数のスコアチェックと平均値を管理する(Python を通す)
切り取り
もっと詳細に見える化する
ここまでのものを csv に出したりすれば、結果のビジュアライズももう少し進むと思うので、バッチファイルはこの辺にしておきます。