マルバツゲームでコードゴルフをやってみた
はじめに
マルバツゲームでコードゴルフをやりました(参加者3人).
勝ち点/コード長 が大きい方から順位が決まります.
コードゴルフというのはいかにコードを短く書くかというやつです.
ルール
C言語のプログラムを1つ書く,このプログラムに求められる入出力は以下の通り
入力
以下のようなマルバツゲームの盤面が与えられる(末尾に改行を含む).(o
:先手 x
:後手)
xox
.o.
o..
出力
次の盤面を同様の形式で返す.例えば上の入力に対しては下のような出力が許される(末尾に改行を含めなければならない).
xox
.o.
ox.
実行環境
公平のためideoneで実行.
勝敗
先手である場合 o
を,後手である場合 x
を縦横斜めのいずれかに3つ揃えたら勝ち.invalidな出力をした場合負け.
順位の決め方
同じ相手と先後交代で2回戦う,総当たり戦を行う.同じプログラムで先手も後手も対応する必要がある.
それぞれの対戦について,勝ち:3点 引き分け:1点 負け:0点
最終的なスコアは,点数の合計/コード長で決める.
自分の戦略
勝ちが3点,引き分けが1点.
短いコードで,先手で引き分けを狙うことに全力を注ぎました.
先手で引き分け,後手で負けだと勝ち点では自分1点,相手4点です.相手よりコード長が
短いプログラムで引き分けるには,相手を誘導する必要があります.
相手のプログラムがある程度賢いならば,初手で隅を選ぶと,2手目に真ん中に置くでしょう.真ん中以外を選ぶと負ける手筋が存在するので,真ん中を選ばざるを得ません.
1手目(自分)
o..
...
...
2手目(相手)
o..
.x.
...
そこで,相手の2手目が真ん中であれば,最低でも引き分けるプログラムを考えました.
具体的には,下の図の順に探索し,空いているマスならそこに石を置く,というルールにしました.単純なルールですが,2手目に真ん中に置かれた時点で負けはありません.
169
425
378
コード
121Byteです.文字化けしているように見える場所は制御文字のDC2
です.
a=11,c,d;main(b){char s[a];read(0,s,a);for(;a--;b+=s[a]);for(;s[d]!=46;d="-H$6 QZ"[c]/9,_c++);s[d]=111+b/69%2*9;puts(s);}
配列外を参照している気もするけど動くからOKなのです.
for(;s[d]!=46;d="-H$6 QZ"[c]/9,_c++);
の部分で先ほどの優先順位の順に探索しています.
後手番でも一応動くようにはなっています.先手番と後手番の判別は,文字の合計を69で割った値を2で割った余りで判断しています.
戦績
作戦通りに決まった試合のログを載せます.
vs 寿司まう
こちらが先手番 o
です.
o..
...
...
o..
.x.
...
o..
.x.
o..
o..
xx.
o..
o..
xxo
o..
ox.
xxo
o..
ox.
xxo
oo.
ox.
xxo
oox
oxo
xxo
oox
というように,狙い通り引き分けです.
結果
駒上(筆者) | 寿司まう | 匿名A | |
---|---|---|---|
駒上(筆者) | 0勝1敗1分 | 2勝0敗0分 | |
寿司まう | 1勝0敗1分 | 2勝0敗0分 | |
匿名A | 0勝2敗0分 | 0勝2敗0分 |
勝敗は上のようになりました,
順位 | 名前 | コード長 | 勝ち点 | スコア |
---|---|---|---|---|
優勝 | 駒上 | 121バイト | 7 | 0.0579 |
準優勝 | 寿司まう | 717バイト | 10 | 0.0139 |
第3位 | 匿名A | 398バイト | 0 | 0 |
勝ち点/コード長 が大きい方から順位が決まるので,優勝です.やったぜ.
おわりに
はじめてのコードゴルフ,色々参考にしました.
特に役立ったのは以下の記事です.
Discussion