paiza開発日誌

IT/Webエンジニア向け総合求人・学習サービス「paiza」(https://paiza.jp ギノ株式会社)の開発者が開発の事、プログラミングネタ、ITエンジニアの転職などについて書いています。

【解答コード公開】異世界を救う召喚プログラマ続出!その方法を解説


paizaで先月から公開しておりました、異世界転生ファンタジーRPGロジックサマナー~閃光の召喚プログラマ(略してロジサマ)にたくさんのご挑戦ありがとうございました!

今回はランキング問題の解法を解説いたします。(※解答コードはPythonで記述しています)

(ロジックサマナーの問題は、解答コードや解法など、ご自由にブログ等で公開していただいて構いません!また、プレゼント抽選の期間は終了しておりますが、問題には何度でも挑戦していただけます)

paiza.jp

ロジックサマナーランキング問題「魔法の呪文」 (封印レベルS)

あなたは魔法使いの見習いです。今日、あなたは修行のために魔法の呪文の練習をすることにしました。

H 行 W 列からなるブロックの集まりを使って、練習をしようとしています。

ブロックには赤・青・緑の 3 種類の色があります。以下は入力例 1 を図にしたものです。
f:id:paiza:20170622135826p:plain

今、このブロックの集まりに「モノケシ」の呪文を使っていきます。「モノケシ」の呪文は特定のブロックを指定して使います。

この呪文が使われたブロックは、縦横で隣接する同じ色のブロック同士がくっつき、その後消滅します。

消滅した後、消えたブロックの上にあった他のブロックは、下にある他のブロックにぶつかるまで、または最下段に到達するまで落下します。

以下は、入力例 1 で 3 列目の一番上のブロックを消したときの図です。
f:id:paiza:20170622135846p:plain

あなたはまだ見習いの魔法使いであるため、「モノケシ」の呪文を N 回までしか使うことができません。このとき、N 回以内にできるだけ多くブロックを消してください。

消したブロックの数が多く、呪文を使った回数が少ないほど良いスコアとなります。

ランキングで使われるスコアは (消したブロック数) + (呪文を使える回数 N - 呪文を使った回数) の式で計算され各ブロックの集まりごとのスコアの合計で計算されます。

f:id:paiza:20170622145056p:plain
f:id:paiza:20170622145101p:plain

問題ページはこちら

この問題は、正解を出すだけなら簡単です。どんな消し方でもよいので、出力形式に従って出力さえしていけば、正解にはなります。

まずは「上から消していくと、凸のような形になって隣接するブロックが減りそうだな」という最低限の考え方で書いたのが下記のコードです。とにかく下1行を消し続けます。この時、何もない場所で呪文を使ってしまわないよう、ブロックの状態をシミュレーションした結果を保持し、何もない場合はその列を無視するという処理を入れています。

このコードを提出すると、スコアは 819 となります。これだけでも結構いいスコアですね。

ただ、下から1行目よりも下から2行目や左右2列目などの方が、より他のブロックと隣接していてよさそうな気がしますよね。

少し方針を変えて、右下から1色ずつ消す方法で書いてみたコードがこちらです。

一見、ブロック同士がよりくっつきやすくなって、消えるブロックの数が増える…?という気がしますが、提出したところ、スコアは 533 とむしろ下がってしまいました。(ちなみに赤、緑、青のどれからチェックするかで少し点数が変わります)

なぜスコアが下がるのかですが、この解き方では、手数が最大で 100 で 最大 2500 の盤面にまんべんなく赤、緑、青が孤立した形で配置されていた場合に、各色約833ブロックずつ存在することになります(割り切れないので1ブロックどれかの色が多くなります)。たった100手しか使えないとなると、どれか1色を消している間に手数が尽きてしまいますので、あまり良いやり方とは言えませんよね。


入力例の図では、例えば青から消していった場合、3手だけだと青が全て消えただけで終了となってしまいます。一方で、緑→青→赤の順で消せば、緑が2つ、緑が3つ、青が5つと都合よく消えますね。小さい盤面である程度の手数があれば、都合よくたくさん消えてくれることもあります。

今度は、単純に消せる数を増やせそうな、できるだけ大きな塊を消していく方法で考えてみましょう。この解き方の場合、入力例で考えてみると、緑が3つ消え、次に青が5つ消え、緑が2つ消えます。

このコードを提出すると 3782 となかなか高いスコアをとることができました。

今回はこのような、大きな塊を消していく方法を最低限の模範解答として想定していました。

もちろんさらに踏み込んで考えると、 N手先まで試して消えた数が多い方を選ぶとか、同じサイズの塊があった場合にどちらを優先するのか…などなど、いろいろな最適化が考えられますので、ぜひ挑戦してみてください!


余談ですが……最も簡単かつ卑怯な解法です。

何も考えずに 0 手、つまり何も消さないという出力をするだけで、 310点が取れてしまいます。スコアの計算上、消した数は 0 ですが、使っていい手数の 310手分が点数となっています。

もちろん、このやり方をしてもpaizaランクS相当のスキルとは言えませんのであしからず…。


ロジックサマナー~閃光の召喚プログラマ』では、このほかにもさまざまな難易度のプログラミング問題が「封印」としてプレイヤーの前にたちはだかります。プログラミング初心者向けの問題も多数ございますので、「ランキング問題は難しくて無理……」という方もぜひ挑戦してみてください!
paiza.jp




paiza転職は、転職時のミスマッチをなくし、エンジニアがより技術面にフォーカスしたやりがいある仕事を探せる転職サービスです。プログラミングスキルチェック(コーディングのテスト)を受けて、スコアが一定基準を超えれば、書類選考なしで複数の会社へ応募ができます。
paiza.jp
まずはスキルチェックだけ、という使い方もできます。すぐには転職を考えていない方でも、自分のプログラミングスキルを客観的に知ることができますので、興味がある方はぜひ一度ご覧ください。
paiza.jp

ITプログラマ・エンジニア向け転職・就活・学習サービスのpaiza