Pythonでチェス盤上のナイト(騎士)同士が互いに攻撃しているか判定する方法
ここでは、二次元のバイナリ行列を扱います。この行列は長方形のチェス盤を表しており、0 は空きマス、1 はナイト(騎士)がいるマスを意味します。ナイトは、実際のチェスと同じように、水平方向に2マス・垂直方向に1マス、あるいは垂直方向に2マス・水平方向に1マス移動できます。
この問題の目的は、盤上に存在するどれか2つのナイトが互いに攻撃し合っているかどうかを判定することです。
例として、次のような入力が与えられた場合を考えます。
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 0 | 1 | 0 |
この場合、2つのナイトが互いに攻撃可能な位置にあるため、出力は True になります。
解法のアプローチ
この問題は、以下の手順で効率的に解くことができます。
- まず、行列の行数と列数を取得します。
- すべてのマスを順番に走査します。
- ナイトが存在するマスを見つけたら、その下方4方向、つまり (r+1, c-2)、(r+1, c+2)、(r+2, c-1)、(r+2, c+1) の位置に別のナイトがいないかを確認します。
- 攻撃関係にあるナイトのペアが1組でも見つかれば、
Trueを返します。 - 最後まで見つからなければ、
Falseを返します。
ここで重要なポイントは、上方のマスをチェックしていない点です。これは、すでに走査済みのペアを二重に確認する無駄を避けるためです。各ナイトのペアは必ず一度だけ評価されるため、計算量を半分に抑えることができます。
それでは、実際の実装例を見てみましょう。
実装例
class Solution: def solve(self, A): row, col = len(A), len(A[0]) for r in range(row): for c in range(col): if A[r][c]: for nr, nc in ((r+1, c-2), (r+1, c+2), (r+2, c-1), (r+2, c+1)): if 0 <= nr < row and 0 <= nc < col and A[nr][nc]: return True return False ob = Solution() mat = [[0,0,0,0,0], [0,1,0,0,0], [0,0,0,1,0]] print(ob.solve(mat))
入力
[[0,0,0,0,0], [0,1,0,0,0], [0,0,0,1,0]]
出力
True
このコードでは、盤面全体を一度だけ走査し、各ナイトについて下方4方向のみを確認するため、時間計算量は O(行数 × 列数) となり、非常に効率的です。チェス盤のようなグリッド問題において、対称性を利用して探索範囲を絞るテクニックは、他の多くの問題にも応用できます。
-
Pythonでクイーンがチェス盤上の特定のマスを攻撃できるか判定する方法
チェス盤上に、クイーンと相手の駒の位置を表す2つの座標があるとします。それぞれ Q(クイーン)と O(相手の駒)とします。ここで、クイーンが相手の駒を攻撃できるかどうかを判定する必要があります。ご存知のとおり、クイーンは同じ行、同じ列、そして斜め方向に攻撃することができます。 例えば、入力が Q = (1, 1)、O = (4, 4) の場合、出力は True になります。これは、Q が斜め方向に (4, 4) へ移動して攻撃できるためです。 解法のアプローチ この問題を解くには、以下の手順に従います。 Q の x 座標と O の x 座標が同じ場合は True を返す(同じ行) Q の
-
【初心者向け】Pythonのissuperset()メソッドの使い方をわかりやすく解説
はじめにこの記事では、Pythonのissuperset()メソッドについて、基本的な仕組みから実際のコード例まで詳しく解説します。issuperset()は、セット(集合)に対して使用できるメソッドで、引数として渡されたセットのすべての要素が、呼び出し元のセットに含まれているかどうかを判定します。呼び出し元のセットBが、引数のセットAのすべての要素を含んでいる場合 → True を返すセットAの要素がすべてBに含まれていない場合 → False を返すつまり、「BがAの上位集合(スーパーセット)であるかどうか」を判定するためのメソッドです。基本構文B.issuperset(A)この式は、Bが