🔙
🔝

Bランク実力確認問題セット2

ヒントを頼りにプログラムを組んでみてください。

俳句

俳句

    一行の文字列から、半角スペース区切りで3つの文字列に分割する問題です。

  • 入力を一行で受け取ってから分割する場合
    .split() メソッド

  • 入力ついでに分割してしまう場合
    横並びの文字列を入力する - input().split()

  • 問題集やスキルチェックで頻繁に使うのは後者ですが、 .split() メソッドの機能自体を理解しておくと応用が利くようになります。


    .split() メソッドを使わない原始的な方法も考えられますが、そこまでする必要は無いでしょう。

総和と総積

総和と総積

    総和はsum()関数を使えば簡単ですが、この問題では総積も同じ数列を使って求めます。よって別々に計算するよりは同時に計算したほうがラクそうです。

    数値を1つを入力して足し算と掛け算をして、それぞれの変数に計算結果を保存していきます。

    変数に都度保存していくというこの方法はあまり賢くないように思えるかもしれませんが、基本的な手法でもあり、様々なアルゴリズムでも使われています。「一行でも少なく、少しでも簡潔に」を意識してばかりいると、かえってわかりにくいプログラムとなることに繋がってしまいます。

    この後の問題もこの「計算結果を都度変数に保存していく」テクニックが使われるようです。関数を使うとかえって効率悪くなることもあることを踏まえつつ、この問題のプログラムを書いてみてください。

陣地取りゲーム

陣地取りゲーム

考え方

考え方

    まずは問題を理解してイメージしてみましょう。問題の入力例1 を使って進めていきます。

    『A くんと B くんは、1 列に並んだ N 個のマスでゲームをしています。
    ゲーム開始時、すべてのマスはどちらの陣地でもありません。』

    • N 個のマスがある
    • すべてのマスはどちらの陣地でもない

    入力例1 では、N = 5 となっていますので、マスが5つあることになります。

         

    次に、このゲームのルール説明です。

    『どちらの陣地でもないマスを獲得すると、そのマスはそのプレイヤーの陣地になる。』

    要するに空いているマスは占拠できるということです。

    12345
        



    『すでに自分の陣地であるマスを獲得しようとしても何も起きない。』

    12345
        
       
     

    何かイベントが発生するということはなく、静かに陣地を増やしていくだけのゲームのようです。




    『相手の陣地を奪うことはできない。』

    12345
       
     
       

    野蛮な争いはしないようです。

    最後に、より多くの陣地を獲得した方の勝ちとなります。

プログラム構成を考える

プログラム構成を考える

  • マスの入力が用意されていませんので、自分で作る必要があります。

  • 各プレイヤーが獲得した陣地のカウントをする必要があります。

  • 勝敗を判定する必要があります。


  • どのようなプログラムにするにも、最低限この3つの要素は必要になりそうです。

案 - その1

マスをリストでつくる

    N 個のマスをリストで用意します。入力例1 では N = 5 となっていますので、5つのマスを用意します。

    cells = ['', '', '', '', '']
    

    これを N 個つくる方法に書き換えてください。'' の代わりに None とかでもイケます。👍

    次に、各プレイヤーが占拠した陣地をカウントする為の変数を用意します。この変数を使って、最後に勝敗の判定をします。

    ゲーム開始です。1ターンずつ順番に入力をし、ルールに則って空白地を占拠していきます。このときに、陣地の数もカウントアップしておきます。

    これを Q ターン行います。A と B が交互に行うわけではありませんので注意。

    すべてのターンが終了したら、勝敗の判定を行い、結果を画面に出力してプログラム終了です。

案 - その2

まとめてカウントする

    カウントはターン毎でなく、全てのターン終了後に行うこともできます。'A' の数 'B' の数をまとめて数えて変数に代入すれば、初めにカウント用の変数を初期化して用意する必要がなくなります。

    • .count() メソッドを使う
    • from collection import Counter モジュールを呼び出してアレを使う

    カウントする方法は他にもあります。なかなか寝付けない時にでもたくさんの方法を考えてみてください。😊

案 - その3

セットを使う

    初めは空のセットを用意し、番号をセットに加えていくと同時にカウントアップする方法です。セットに入っている値(番号)は、A もしくは B が占拠済みのマスを指しています。この方法ならば初めに N マスを用意しておく必要がありません。この方法はリストでも可能ですが、今回の場合は効率の良い探索処理をしてくれるセットのほうが向いています。

    プログラム構造はほとんど変わらないので、試してみてください。

おまけ

いろいろ考えていじりまくってみましょう

    『すでに自分の陣地であるマスを獲得しようとしても何も起きない。』
    『相手の陣地を奪うことはできない。』

    この2つの処理方法は同じです。占拠しようとしているマスが既に自分の陣地であっても相手の陣地であっても何もしないからです。「何もしない」ので、プログラムを組んでいるその場で気付いたかとも思われますが。

    「何もしない」という部分を、今度はあえて continue を使って組み換えてみてください。そしてどんな見た目になるのかを実際に確認してみてください。

    その他、特定の処理を関数にしてみたり、関数型で書いたりもしてみてください。

陣地取りゲーム 2D

陣地取りゲーム 2D

問題を整理する

問題を整理する

    前回は直線だったマスが、今度は面になっています。ということは二次元リストを使うのだろうということは想像つくでしょう。

    今度はルールが複雑化しています。


    『どちらの陣地でもないマスを獲得すると、そのマスはそのプレイヤーの陣地になる。』

    これは前回同様のルールです。


    『相手の陣地を獲得しようとすると、そのマスはどちらの陣地でもなくなる(中立化される)。』

    言い換えれば空白のマスに戻るということです。


    『すでに自分の陣地であるマスを再度獲得しようとすると、そのマスは完全にそのプレイヤーの陣地となり、それ以降は相手に奪われたり、中立化されたりしない(ロックされる)。』

    同じマスに続けて二回訪れないと「占拠した」ことにならないということです。餌を見つけた時のアリみたいですね。😆


    『すでにロックされているマスは、誰が行っても状態は変化しない。』

    これも前回の『すでに自分の陣地であるマスを獲得しようとしても何も起きない。』『相手の陣地を奪うことはできない。』と同様、「何もしない」という処理になりそうです。

    ゲームの判定方法も前回同様、より多くの陣地を獲得したほうの勝ちとなっています。

二次元リストでマップをつくる

二次元リストでマップをつくる

    二次元のリストでマップを作る際に注意しなければならないのが、コピーの問題です。一次元リストは、

    cells = [''] * N
    

    と書くことができましたが、二次元リストは、

    cells = [[''] * N] * M]
    

    と書くことができません。(理由は省略)
    そういえばうちのサイト、二次元マップの作り方を扱ってなかったな・・・。

    そ、そんな時は、文を使って一次元リストを増やしましょう!😆

ルールに基づいてゲームを進める

「占有」と「占拠」

    「占有」とは、『自分の所有とすること (大辞泉より)』です。
    「占拠」は、『ある場所を占有して他人を寄せつけないこと。(大辞泉より)』です。「占領」も同じ様な意味合いです。

    占有するだけでは、相手プレイヤーに中立化されてしまいます。占有してから続けてもう一度同じマスを獲ることで占拠 (ロック)することができます。

    マップには、空白地は '' とし、各プレイヤーは AB となっているので、占有の時は a b と、小文字で表記することにしておきましょうか。


    前回と比べて今回の違いは、マップが二次元となったところと、上記のルールが新たに追加されたところです。二次元マップが作れたら、残りはこのルールに集中してプログラムを組んでいきます。

    文では次のように書きます。

    • まず、空白地 '' になっているところは占有となります。プレイヤーAの場合は a、プレイヤーBの場合は b に変更します。
    • もし、相手の占有地を獲ろうとした時は、そこは空白地に戻します。
    • もし、獲ろうとしたマスが自分の占有地だった時は、占拠(ロック)になります。a の時は A へ、b の時は B へ変更します。

    • それ以外は「何もしない」ことになります。『すでにロックされているマスは、誰が行っても状態は変化しない。』に該当します。

    二次元リストへのアクセスがちょっとアヤシイという方は 2章 二次元リスト を読んで確認してください。

カウント処理

カウントをどこで行うか

    問題文に書かれている「陣地」とは、AB の他に、ab も該当します。つまりプレイヤーAの陣地は aA、プレイヤーBの陣地は bB の所になります。

    占有したところは単純にカウントを +1 するだけで良いのですが、占拠した時と中立化した時とでも、それぞれカウントを考慮しなければなりません。

    どこでどのようなカウントを行えばよいか、考えてみてください。

最後に

最後に

    残りは勝敗判定です。正しくカウント処理ができていれば、前回と同様の記述で問題ないはずです。

    前回から追加されたルールと、それに伴うカウント処理が複雑で、素直に書いて出来上がったプログラムもちょっと読みにくくなっている状態にあるかもしれません。きちんと整理できていればそれなりに読みやすくはなっているかと思われますが、他にもどのような構造のプログラムで作れるか、いろいろ考えていじりまくってみてください。(ヒント: 文は辞書を使うと簡潔に書けることがあります)
    関数型やクラス型でも書いてみましょう。

    ランクBの問題はいろんな組み方ができて遊び甲斐がありますので、一回クリアしたら終わりとせず、考えまくってたくさんのプログラムを書きまくってみてください。👍