paizaラーニング問題集「移動が可能かの判定・幅のある移動」を解いてみた

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

▼考え方

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

1. 現在向いている方角を示す変数neswと、移動の向きと移動するマス数を格納したリストdlを、関数caldistanceに渡して、y,x座標の移動距離を計算します。

2. 現在の座標(y,x)と1の戻り値(y,x座標の移動距離)を関数nextpositioncheckに渡して、移動が可能かどうかを判定します。移動が不可能ならば、障害物がある旨のメッセージと障害物の座標、あるいは、マップの範囲外である旨のメッセージを返します。2に関しては、以下に詳細な説明を示します。

3. 移動後の座標と移動後の向いている方角を求めます。

[考え方2の詳細な説明]

2.1
y軸方向の移動(dyx[1] == 0)か、x軸方向の移動(dyx[0] == 0)かで処理を分けます。

2.2. 
y軸方向の移動の処理をするために、2次元リストSから列を抽出しリストtmpに格納します。

2.3.
y軸の負の方向(dyx[0] < 0)に移動するのか、正の方向に移動するのかで、処理を分けます。

2.4.
y軸の負の方向に移動することを考えます。移動(y+dyx[0]からy、あるいは、0からy)の間に障害物がある場合は、障害物がある旨のメッセージと障害物の座標を返します。

2.5.
移動の間に障害物がないがマップの範囲外に移動してしまう場合は、マップの範囲外である旨のメッセージを返します。

2.6.
y軸の正の方向に移動することを考えます。移動(yからy+dyx[0]+1、あるいは、yからH-1)の間に障害物がある場合は、障害物がある旨のメッセージと障害物の座標を返します。

▼コード
```py
H,W,sy,sx,N = map(int,input().split())

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

# dl: 移動の向きと移動するマス数を格納したリスト
dl = [list(input().split()) for _ in range(N)]

# nesw: 現在向いている方角を示す変数 0:北,1:東,2:南,3:西
nesw = 0

# y: 現在のy座標を示す変数
y = sy

# x: 現在のx座標を示す変数
x = sx

# caldistance: y,x座標の移動距離を計算を計算する関数
def caldistance(nesw,dl_i):

    # dy: y座標の移動距離を示す変数
    dy = 0
    # dx: x座標の移動距離を示す変数
    dx = 0
    
    dl_i[1] = int(dl_i[1])

    if dl_i[0] == "L":
    
        if nesw == 0:
            dx -= dl_i[1]
        elif nesw == 1:
            dy -= dl_i[1]
        elif nesw == 2:
            dx += dl_i[1]
        else:
            dy += dl_i[1]

    else:
    
        if nesw == 0:
            dx += dl_i[1]
        elif nesw == 1:
            dy += dl_i[1]
        elif nesw == 2:
            dx -= dl_i[1]
        else:
            dy -= dl_i[1]
    
    return [dy,dx]

# nextpositioncheck: 移動が可能かどうかを判定する関数
def nextpositioncheck(y,x,dyx):

    # 考え方2.1.
    if dyx[1] == 0:

        # 考え方2.2.
        # tmp: 2次元リストSから列を抽出し可能するリスト
        tmp = [r[x] for r in S]

        # 考え方2.3.
        if dyx[0] < 0:

            # 考え方2.4.
            if "#" in tmp[max(y+dyx[0],0):y]:
                # hash_index: 障害物の座標を格納する変数
                hash_index = tmp[max(y+dyx[0],0):y].index("#")
                return ["Stop_#_y",y-(len(tmp[max(y+dyx[0],0):y])-(hash_index+1))]

            # 考え方2.5.
            else:
                if y+dyx[0] <= -1:
                    return ["Stop_om",0]
                    
        else:
        
            # 考え方2.6.
            if "#" in tmp[y:min(y+dyx[0]+1,H-1)]:
                hash_index = tmp[y:min(y+dyx[0]+1,H-1)].index("#")
                return ["Stop_#_y",y+hash_index-1]

            else:
                if y+dyx[0] >= H:
                    return ["Stop_om",0]
                    
    else:
    
        if dyx[1] < 0:
            
            if "#" in S[y][max(x+dyx[1],0):x]:
                hash_index = S[y][max(x+dyx[1],0):x].index("#")
                return ["Stop_#_x",x-(len(S[y][max(x+dyx[1],0):x])-(hash_index+1))]

            else:
                if x+dyx[1] <= -1:
                    return ["Stop_om",0]
        else:
            
            if "#" in S[y][x:min(x+dyx[1]+1,W-1)]:
                hash_index = S[y][x:min(x+dyx[1]+1,W-1)].index("#")
                return ["Stop_#_x",x+hash_index-1]

            else:
                if x+dyx[1] >= W:
                    return ["Stop_om",0]
    
    return ["",0]

for i in range(N):

    # 考え方1.
    # dyx: y,x座標の移動距離に関する情報を格納するリスト
    dyx = caldistance(nesw,dl[i])

    # 考え方2.
    # checkresult: 移動が可能かどうかの判定結果に関する情報を格納するリスト
    checkresult = nextpositioncheck(y,x,dyx)

    # 考え方3.
    if checkresult[0] == "Stop_om":
        y = max(0,min(y+dyx[0],H-1))
        x = max(0,min(x+dyx[1],W-1))
        print(y,x)
        print("Stop")
        exit()
    
    elif checkresult[0] == "Stop_#_y":
        y = checkresult[1]
        print(y,x)
        print("Stop")
        exit()
    
    elif checkresult[0] == "Stop_#_x":
        x = checkresult[1]
        print(y,x)
        print("Stop")
        exit()

    else:
        y += dyx[0]
        x += dyx[1]
        print(y,x)

    if dl[i][0] == "L":
        nesw -= 1
    else:
        nesw += 1
    
    if nesw > 3:
        nesw = 0
    elif nesw < 0:
        nesw = 3
```