Pythonで挑むボス戦アルゴリズム:戦闘員とボスの戦力を判定して勝敗行をふるい分ける方法
問題の概要
0と1だけで構成されたリスト fighters(戦闘員)と、同じく0と1からなる二次元リスト(行列)bosses(ボス)が与えられます。fighters内の「1」は戦闘員1人を表し、bossesの各行に含まれる「1」はその行にいるボスを表します。
戦闘員たちがあるボスの行に勝てるのは、戦闘員の総数がその行のボスの数より多い場合です。つまり、勝てない(倒しきれない)行だけを残し、撃破されたボスの行を取り除いた新しい bosses の行列を返すのがこの問題の目的です。
入力例
たとえば、fighters = [0, 1, 1](戦闘員は2人)で、bosses が次のような行列だったとします。
| 0 | 1 | 1 |
| 0 | 0 | 0 |
| 0 | 0 | 1 |
| 0 | 1 | 1 |
| 1 | 1 | 1 |
このとき、戦闘員2人に対してボスが2体以上いる行、すなわち [0, 1, 1] と [1, 1, 1] のみが残り、出力は次のようになります。
| 0 | 1 | 1 |
| 1 | 1 | 1 |
解き方のアプローチ
この問題はシンプルな集計とフィルタリングで解決できます。手順は以下の通りです。
fighter_cnt:fightersの全要素の合計(= 戦闘員の総数)を求めます。result: 結果を格納するための新しい空リストを用意します。bossesの各行rowについて以下を繰り返します。もし
fighter_cnt <= row の要素の合計であれば、その行は撃破されていないためresultの末尾に追加します。
最後に
resultを返します。
ポイントは条件式の向きです。「戦闘員の数がボスより多い行」が敗北した行なので、それ以外(fighter_cnt <= ボスの数)の行だけを残せばよい、というわけです。
実装例
理解を深めるために、実際のPythonコードを見てみましょう。
class Solution:
def solve(self, fighters, bosses):
fighter_cnt = sum(fighters)
result = []
for row in bosses:
if fighter_cnt <= sum(row):
result.append(row)
return result
ob = Solution()
fighters = [0, 1, 1]
bosses = [[0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 1, 1]]
print(ob.solve(fighters, bosses))入力
[0, 1, 1], [[0, 0, 0], [0, 0, 1], [0, 1, 1], [1, 1, 1]]
出力
[[0, 1, 1], [1, 1, 1]]
計算量とまとめ
このアルゴリズムの時間計算量は O(n × m) です(n は bosses の行数、m は各行の要素数)。各行の合計を一度ずつ計算して比較するだけなので、非常に効率的です。
また、Pythonのリスト内包表記を使えば、さらに簡潔に次のように書くこともできます。
def solve(fighters, bosses):
cnt = sum(fighters)
return [row for row in bosses if cnt <= sum(row)]「合計値を比較して条件に合う行だけを抽出する」というこのパターンは、データのフィルタリング全般に応用できる基本的かつ重要なテクニックです。ぜひマスターしておきましょう。
-
【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説
はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが
-
Pythonのアンダースコア(_)の使い方を徹底解説!シングルとダブルの違いとは
Pythonでは、状況に応じてシングルアンダースコア(_)とダブルアンダースコア(__)を使い分けます。一見すると単なる記号に見えますが、それぞれに明確な役割や慣習が存在します。 Pythonでアンダースコアが使われる主なケースは以下のとおりです。 インタプリタで最後に評価した式の値を保持したい場合 特定の値を意図的に無視したい場合 変数名や関数名の宣言において特別な意味を持たせたい場合 数値リテラルの桁区切りとして使いたい場合 国際化(i18n)や地域化(l10n)の関数として使いたい場合 それでは、それぞれのケースについて具体例を見ていきましょう。 インタプリタでの使用 Pythonの