paizaラーニング問題集「時刻に伴う移動」を解いてみた

▼問題

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

▼考え方

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

1. へびの移動は最大100回なので、100回ループを回します。

2. 以下の3つの引数を関数caldistanceに渡して、y,x方向の移動距離を計算します。移動距離の情報を返します。関数に渡す引数は、①現在の時刻を示す変数i、②現在向いている方角を示す変数nesw、③方向転換する時刻と転換する向きを格納したリストtd 1行ずつです。

3. 現在の座標(y,x)と2の戻り値(y,x方向の移動距離)を関数nextpositioncheckに渡して、移動が可能かどうかの判定を行います。移動が不可能ならば"stop"を返します。移動が可能ならば"Go"を返します。

4. 3の戻り値が"stop"の場合は、その旨を出力し処理を終了します。"Go"の場合は、移動後の座標を計算して出力します。あと、方向転換した場合は向いている方角を更新します。

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

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

    # dy: y座標の移動距離を示す変数
    dy = 0

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

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

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

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

    if (y+dyx[0] <= -1 or y+dyx[0] >= H) or (x+dyx[1] <= -1  or x+dyx[1] >= W):
        return "stop"

    if dyx[1] == 0:
    
        S_r = [r[x] for r in S]

        if dyx[0] < 0:
            
            S_r_sub = S_r[max(y+dyx[0],0):y]
            if "#" in S_r_sub:
                return "stop"
                    
        else:
            
            S_r_sub = S_r[y:min(y+dyx[0]+1,H-1)]
            if "#" in S_r_sub:
                return "stop"
            
    else:
    
        if dyx[1] < 0:
            
            S_r_sub = S[y][max(x+dyx[1],0):x]
            if "#" in S_r_sub:
                return "stop"

        else:
            
            S_r_sub = S[y][x:min(x+dyx[1]+1,W-1)]
            if "#" in S_r_sub:
                return "stop"

    return "Go"

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

H,W,sy,sx,N = map(int,input().split())

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

# td: 方向転換する時刻と転換する向きを格納したリスト
td = [list(input().split()) for _ in range(N)]

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

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

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

# j: リストtdを1行ずつ操作するための変数
j = 0

# 考え方1.
for i in range(100):

    # 考え方2.
    # dyx: y,x座標の移動距離に関する情報を格納するリスト
    dyx = caldistance(i,nesw,td[j])
    
    # 考え方3.
    # checkresult: 移動が可能かどうかの判定結果の文字列を格納するリスト
    checkresult = nextpositioncheck(y,x,dyx)

    # 考え方4.
    if checkresult == "stop":
    
        print("Stop")
        exit()
    
    else:
        
        y += dyx[0]
        x += dyx[1]

        print(y,x)

        if i == int(td[j][0]):
            
            if td[j][1] == "L":
                nesw -= 1
            else:
                nesw += 1
    
            if nesw > 3:
                nesw = 0
            elif nesw < 0:
                nesw = 3
            
            j += 1
```