【Aランクアップコース-3・4・5】マップの判定・横/ マップの判定・縦/マップの判定・縦横(paizaランク C 相当)

マップの判定・横 (paizaランク C 相当)
https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_snake_map_step3

H,W = map(int,input().split())
S = [list(input()) for _ in range(H)]
for j in range(H):
    for i in range(W):
        # 一番左端
        if i == 0:
            if S[j][i+1] == "#":
                print(j,i)
        # 一番右端
        elif i == W-1:
            if S[j][i-1] == "#":
                print(j,i)
        else:
            if S[j][i+1] == "#" and S[j][i-1] == "#":
                print(j,i)

これは難しくないです。。。というほどではないですが、
まず、マップを作成したあと、
一番左端、右端、それ以外で場合分けをして、
それぞれのときの条件に当てはまったら出力。というやり方ですね。
見た目的にはスマートじゃないかなという気もするのですが、
他にスマートな書き方が思いつかず。
回答を見ると

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]

for y in range(h):
    for x in range(w):
        if x == 0 or s[y][x - 1] == "#":
            if x == w - 1 or s[y][x + 1] == "#":
                print(y, x)

for文を2つ重ねるところは同じですね。
ところがその後の条件がちょっと違いますね。
左端、つまりxが0のとき(私ので言うとi = 0のとき)と、一つ前が#であるとき、ですね。
この場合、左側はチェックOKってことになってて、
右側をチェックするというのが次の判定式になっています。
ここはxが右端か、または、一つ後が#であれば条件が成立するので、
このときに出力ってことですね。

なるほど、ロジックを考えるというのはこういうことか〜って思いました。
なんと言えばいいんですかね。
私の場合は座標がその位置にある時の状況で場合分けをしてましたが、この場合だと、毎回座標を作成してチェックしないといけないんですね。
その点、回答の場合は、左側がOKになるときのみ右側のOKチェックを行うということで、判定回数も少ないと思うんですね。
これで説明になってるかな。

勉強になりました!


マップの判定・縦 (paizaランク C 相当)

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_snake_map_step4

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]

for y in range(h):
    for x in range(w):
        if y == 0 or s[y-1][x] == "#":
            if y == h - 1 or s[y+1][x] == "#":
                print(y, x)

ここは簡単でしたね。というのは横の部分を縦に変更して、ロジックもさっき学んだやりかたを
使えば同じようにできます。


マップの判定・縦横 (paizaランク B 相当)

https://paiza.jp/works/mondai/a_rank_level_up_problems/a_rank_snake_map_boss

今までの縦と横を組み合わせる問題です。これだとBランク。
上のコードを組み合わせるとまあこうなりますよね。

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]

for y in range(h):
    for x in range(w):
        if x == 0 or s[y][x - 1] == "#":
            if x == w - 1 or s[y][x + 1] == "#":
                print(y, x)
                
        if y == 0 or s[y-1][x] == "#":
            if y == h - 1 or s[y+1][x] == "#":
                print(y, x)

ところが、これだと間違いです。
結果こうなっちゃうんですよ。

	
0 0
0 0
0 1
0 2
0 2
1 0
1 1
1 2
2 0
2 1
2 2

このときの盤面は、こう。

##.
###
...

この場合、前後左右が#でないといけないんですよね。
だから、(0,0)か(0,2)ということになります。

0 0
0 2

とりあえず、場合分けして、yとxを固定してチェックしたのですが、

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]

for y in range(h):
    for x in range(w):
        if y == 0:
            if x == 0 or s[y][x - 1] == "#":
                if s[y+1][x] == "#":
                    print(y, x)
        elif y == h - 1:
            if x == 0 or s[y][x - 1] == "#":
                if s[y-1][x] == "#":
                    print(y, x)
        else:
            if x == 0 or s[y][x - 1] == "#":
                if s[y-1][x] == "#" and s[y+1][x] =="#":
                    print(y, x)
            else:
                if s[y-1][x] == "#" and s[y+1][x] =="#" and s[y][x+1] == "#" and s[y][x-1] == "#":
                    print(y, x)

やはり失敗
こちらも含まれてしまいました

0 0
0 1
0 2
2 0

回答を見てみました。
回答はちょっと驚きました。。。

な、なるほど。縦・横の条件がandで成立したらprintするやり方。。。
たしかにそうだ。勉強になりました。。。

h, w = map(int, input().split())
s = [list(input()) for _ in range(h)]

for y in range(h):
    for x in range(w):
        flag_row = False
        flag_column = False

        if x == 0 or s[y][x - 1] == "#":
            if x == w - 1 or s[y][x + 1] == "#":
                flag_row = True

        if y == 0 or s[y - 1][x] == "#":
            if y == h - 1 or s[y + 1][x] == "#":
                flag_column = True

        if flag_column and flag_row:
            print(y, x)