paizaラーニング問題集「リバーシの操作」を解いてみた

▼問題

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

▼考え方

この問題を解くために私が考えた内容1.～3.を以下に示します。

1. 盤面のY,X座標に最初の石を置きます。
2. Y,X座標の石から見て、各方向ごとに石があるかをチェックします。この処理は関数set_stonesを用いて行います。各方向とは、上下左右、右斜め下(rightdown)、右斜め上(rightup)、左斜め下(leftdown)、左斜め上(leftup)です。考え方の詳細は以下に示します。
3. 各方向に石があれば、Y,X座標の石と挟むことで、題意に基づき自分の石を置くことができます。これらの処理は関数set_Reversi_stonesを用いて行います。考え方の詳細は以下に示します。

[考え方2.の詳細]
2.1. Y,X座標の石から見て、上方向に石があるかをチェックします。あるならば、関数set_Reversi_stonesに盤面の情報および文字列"up"を送ります。
2.2. Y,X座標の石から見て、右斜め下方向に石があるかをチェックします。あるならば、関数set_Reversi_stonesに盤面の情報および文字列"rightdown"を送ります。

[考え方3.の詳細]
3.1. Y,X座標の石から見て、上方向の盤面を1つずつチェックします。何も置かれていないマスならば(if sub[i] == ".")、題意に基づき自分の石を置きます(S[Y-i-1][X] = "*")。石が置かれていたマスならば(else)、それ以上石を置くことはできないためbreakします。

▼コード
```py
############### 関数処理 ###############

# set_Reversi_stones: 題意に基づき自分の石を置く処理
def set_Reversi_stones(sub,mark):

    # 考え方3.

    # 考え方3.1.
    if mark == "up":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y-i-1][X] = "*"
            else:
                break

    if mark == "down":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y+i+1][X] = "*"
            else:
                break

    if mark == "left":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y][X-i-1] = "*"
            else:
                break

    if mark == "right":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y][X+i+1] = "*"
            else:
                break

    if mark == "rightdown":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y+i+1][X+i+1] = "*"
            else:
                break

    if mark == "rightup":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y-i-1][X+i+1] = "*"
            else:
                break

    if mark == "leftdown":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y+i+1][X-i-1] = "*"
            else:
                break
                
    if mark == "leftup":
        for i in range(len(sub)):
            if sub[i] == ".":
                S[Y-i-1][X-i-1] = "*"
            else:
                break

# set_stones: Y,X座標の石から見て、各方向ごとに石があるかをチェックする関数
def set_stones(Y,X):

    # 考え方1.
    S[Y][X] = "*"

    # 考え方2.
    
    # S_row: Y,X座標の石と同じ列を1列を取り出し格納するリスト
    S_row = [r[X] for r in S] 

    # S_row_sub: Y,X座標の石から見て、上あるいは下方向の盤面の情報を格納するリスト
    S_row_sub = S_row[:Y]

    # 考え方2.1.
    if "*" in S_row_sub:
        set_Reversi_stones(list(reversed(S_row_sub)),"up")

    S_row_sub = S_row[Y+1:]
    if "*" in S_row_sub:
        set_Reversi_stones(S_row_sub,"down")

    # S_sub: Y,X座標の石と同じ行の1行、あるいは、Y,X座標の石から見て斜めの盤面の情報を格納するリスト
    S_sub = S[Y][:X]
    if "*" in S_sub:
        set_Reversi_stones(list(reversed(S_sub)),"left")

    S_sub = S[Y][X+1:]
    if "*" in S_sub:
        set_Reversi_stones(S_sub,"right")

    # 考え方2.2.
    j = 1
    S_sub = []
    while (X+j <= W-1) and (Y+j <= H-1):
        S_sub.append(S[Y+j][X+j])
        j += 1
    if "*" in S_sub:
        set_Reversi_stones(S_sub,"rightdown")
    
    j = 1
    S_sub = []
    while (X+j <= W-1) and (Y-j >= 0):
        S_sub.append(S[Y-j][X+j])
        j += 1
    if "*" in S_sub:
        set_Reversi_stones(S_sub,"rightup")

    j = 1
    S_sub = []
    while (X-j >= 0) and (Y+j <= H-1):
        S_sub.append(S[Y+j][X-j])
        j += 1
    if "*" in S_sub:
        set_Reversi_stones(S_sub,"leftdown")

    j = 1
    S_sub = []
    while (X-j >= 0) and (Y-j >= 0):
        S_sub.append(S[Y-j][X-j])
        j += 1
    if "*" in S_sub:
        set_Reversi_stones(S_sub,"leftup")

############### メイン関数処理 ###############

H,W,Y,X = map(int,input().split())

S = [list(input()) for _ in range(H)]

set_stones(Y,X)

for i in range(H):
    print(*S[i],sep='')
```