CODE VS 2.1 をSQLでやるとどうなる1
CODE VS というコーディングコンテストに参加しました。
CODE VS 2.1 で勝てなかったからネタに
結果は惨憺たるもので、私は1手読みまでで、Largeの条件で9億ぐらいのスコアー。時間とメモリーさえあれば無限に先読み(総当たりで)できるけれど、数手先まで伸ばしても同じスコアーでした。
終わりの方に気づいたのですが、何手先まで読むかというのは間違いでした(当たり前)。1手読みでもう少しスコアーを伸ばせるエレガンスなロジックにして、それで違った条件の手が出現したとき(ブロックを消すべきか、積むべきか迷う局面)をターニングポイントとして記録。何らかの条件を満たしたときチェックポイントとして決め(例えば、ブロックを消す条件になったとき)そのときのスコアーなどが、目標を満たしてないとき、ターニングポイントまで戻る。
というようなやり方ならもっと伸ばせたと思う。
多分、上位の人は、もっとエレガンスなやり方をしていると思うけれど、私が思いついたのはその程度。
何にしても、私はゲームをほとんどしたことがないためか、プログラム以前に、私自身が1ターン毎の局面で「何をもって良い手とするか」という条件を見いだすことができなかった。つまり、ターニングポイントも、チェックポイントも、私には良いものは選べなかったと思うので、スコアーを伸ばせるはずがない……。
ぶっちゃけ、年齢的な衰えも相当に感じたorz
思考力の瞬発力は確実に衰えているな〜、それにしても、後、何日かあれば……。
正直、子供っぽい性格なので本当に悔しい……。
それはともかく、スコアーが出なかったのでじゃあ、ネタにしよう。ということにしました。
私は Java で参戦したのですが、画面イメージは必要ありませんが、データ的には問題のゲームを完全に再現しなければ解けません。そこまでをSQLでやったらどうなるか?ということを書いてみたいと思います。
※ SQLServer2005以上を想定しています。
SQLでやる部分(基本設計)予定
確認用(ある時点のボードの状態を確認する)
SELECT文(PIVOT/クロス集計)
数値羅列テーブル(再帰SQL・テーブルファンクション)
Input情報をDBに入れる
INSERT文(単純に入力する)
以下を繰り返す
Boardにパックを落とす
INSERT SELECT文(一括挿入・分析関数)
※ パックの角度(4通り)× パックが置ける位置の通り
ブロックを消せなくなるまで繰り返す。
消せるブロックを探す
INSERT SELECT文(一括挿入・再帰SQL・CROSS JOIN)
消すお邪魔ブロックを探す
INSERT SELECT文(一括挿入・再帰SQL・CROSS JOIN)
パックを落とす
INSERT SELECT文(一括挿入・分析関数)
繰り返し終わり
スコアーを計算する
UPDATE SELECT文(一括更新・集計関数)
良い手を探す(ここが私には分からない所)
SELECT文(集計関数イロイロ)
不要情報を消す ※特に必要ないけど、場合によってはエライ量になるので
DELETE(一括削除)
繰り返し終わり
最終的にいろんなシミュレーションをしようと思えば、もっと必要になりますが、最低限であれば、SQL文が10個ぐらいあれば事足りる。
ターン毎に区切るのはゲームの仕様上同じですが、Javaなどと違う点は、一気に全通りのパックを落としてしまうところ。この辺が集合理論の SQL の特徴です。
業務SE・PGなら、問題を見た瞬間にこのぐらいまで行って欲しい。
もちろん、上の様なロジックは、私は Javaなどでやる場合と、SQLでやる場合と、ほぼ同時に頭の中にあって、
SQLは一回でできるし、状況も確認しやすいから楽。
メモリーで完結するスピード勝負のコンテストでは SQL は不利。
と判断しました。
具体的な SQL は次回以降ボチボチ書いていきます。
このぐらいが「SQL でできるよね」って判断している人は、実務で設計を考えるとき、全く違う景色で観ています。
違う景色から観れば、RDBMSを使うなら SQL を使えば、工数もパフォーマンスも、本当に劇的に違うものになるのですけどね……。