見出し画像

【Python】paiza問題集の「戦セット」の「線対称と点対称」の解説

こんにちは。maomaoです。

今回は「戦セット」の最終問題である「線対称と点対称」について解説をしたいと思います。

問題集はこちらから

この問題は「#」と「.」でつくられた2次元マップを「線対称」「点対称」「線対称・点対称どちらも含む」「どちらも含まない」に分けていく問題です。

まずは、こちらが解答コード全文です。

N, M = map(int, input().split())

field = []
# 2次元リストマップを作成
for i in range(N):
   sub_field = []
   lines = input()
   for dot in lines:
       sub_field.append(dot)
   field.append(sub_field)

num = 0

for y in range(N):
   for x in range(M):
       if field[y][x] == "#":
           num += 1

yoko = 0
tate = 0
ten = 0
for y in range(N):
   for x in range(M):
       # 線対称ならば(横)
       if field[y][x] == "#" and field[y][M - x - 1] == "#":
           yoko += 1
       # 線対称ならば(縦)
       if field[y][x] == "#" and field[N - y - 1][x] == "#":
           tate += 1
       # 点対称ならば
       if field[y][x] == "#" and field[N - y - 1][M - x - 1] == "#":
           ten += 1

if yoko == num or tate == num:
   if ten == num:
       print("line point symmetry")
   else:
       print("line symmetry")
elif ten == num:
   print("point symmetry")
else:
   print("none")

上記のコードのポイントについてそれぞれ解説したいと思います。

2次元リストマップの作成

field = []
# 2次元リストマップを作成
for i in range(N):
   sub_field = []
   lines = input()
   for dot in lines:
       sub_field.append(dot)
   field.append(sub_field)

paizaでおなじみの2次元リストマップの作成です。
外側リストの「field」、内側リストの「sub_field」変数を持っているところが特徴的です。

これは「sub_field」に行で入力された値を格納し、すべての列を格納したら「field」に格納し、次の行の入力値を格納する処理に移ります。

※2次元リストについてはこちらでも解説しています。

「#」の数を数える

num = 0

for y in range(N):
   for x in range(M):
       if field[y][x] == "#":
           num += 1

今回の問題では2次元マップが「対称」かどうかを調べるものだったので「#」が「対称」になっている数=「#」の数と等しいと考え、まずは上記のコードであらかじめ2次元リストにある「#」の数を数えています。

「#」が「対称」になっている数を数える

yoko = 0
tate = 0
ten = 0
for y in range(N):
   for x in range(M):
       # 線対称ならば(横)
       if field[y][x] == "#" and field[y][M - x - 1] == "#":
           yoko += 1
       # 線対称ならば(縦)
       if field[y][x] == "#" and field[N - y - 1][x] == "#":
           tate += 1
       # 点対称ならば
       if field[y][x] == "#" and field[N - y - 1][M - x - 1] == "#":
           ten += 1

2次元リストにある「#」が「線対称」と「点対称」になっているかカウントしていきます。

判定

if yoko == num or tate == num:
   if ten == num:
       print("line point symmetry")
   else:
       print("line symmetry")
elif ten == num:
   print("point symmetry")
else:
   print("none")

最後に「線対称」「点対象」「線対称・点対象どちらも含む」「どちらも含まない」のどれかを判定し結果を出力します。

最後に

今回のようなBランク相当の問題になると難易度が上がってくると感じます。解答のコツとしては問題を見てきちんと理解すること、一つ一つの処理を分解して書くことが大事になります。
あとはしっかりデバックして変数の中身を見て確認するのが大事です。

実際、私が解答で詰まった際は、もう一度問題文を読み直し、ノートにポイントを書き出して理解していくことを大事にしています。

この記事が気に入ったらサポートをしてみませんか?