0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

paizaラーニング問題集「へび」を解いてみた

Posted at

▼問題

▼考え方

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

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

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

  3. 現在の座標(y,x)と2の戻り値(y,x方向の移動距離)を関数nextpositionに渡して、移動が可能かどうかの判定を行います。移動が不可能ならば"stop"を返します。移動が可能ならば"ok"を返します。さらに、次の座標を返します。考え方3の詳細は、以下に示します。

  4. y軸方向において、スタート位置を含む移動の際に通ったマップのマスを'*'に変更します。

  5. x軸方向において、スタート位置を含む移動の際に通ったマップのマスを'*'に変更します。

  6. 移動後の座標を現在の座標に設定します。

  7. 方向転換した場合は向いている方角を更新します。

[考え方3の詳細]
3.1
y軸方向の移動(dyx[1] == 0)か、x軸方向の移動(dyx[0] == 0)かで処理を分けます。
3.2
y軸方向の移動の処理をするために、2次元リストSから列を抽出しリストS_rに格納します。
3.3
y軸の負の方向(dyx[0] < 0)に移動するのか、正の方向に移動するのかで、処理を分けます。
3.4
y軸の負の方向に移動することを考えます。移動(y+dyx[0]からy、あるいは、0からy)に際して、障害物("#")があるか、自分の身体("*")があるか、マップ外かどうかを判定します。(移動に際し、障害物や自分の身体がある場合は)関数calforwordindexを用いてその位置を計算します。

▼コード

############### 関数処理 ###############

# 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]

# calforwordindex: 障害物や自分の身体の位置を計算する関数
def calforwordindex(S_r_sub,mark):
    
    return [l for l in range(len(S_r_sub)-1,-1,-1) if S_r_sub[l] == mark]

# nextposition: 移動が可能かどうかを判定と、次の座標を返す関数
def nextposition(y,x,dyx):

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

        # 考え方3.2.
        # S_r: 2次元リストSから列を抽出し格納するリスト
        S_r = [r[x] for r in S]

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

            # 考え方3.4.
            # S_r_sub: 移動予定の部分を抽出し格納するリスト
            S_r_sub = S_r[max(y+dyx[0],0):y]

            if "#" in S_r_sub:
                index = calforwordindex(S_r_sub,"#")
                return ["stop",y-(len(S_r_sub)-(index[0]+1)),x]
                
            if "*" in S_r_sub:
                index = calforwordindex(S_r_sub,"*")
                return ["stop",y-(len(S_r_sub)-(index[0]+1)),x]

            if ("#" not in S_r_sub) and ("*" not in S_r_sub) and (y+dyx[0] <= -1):
                return ["stop",max(0,y+dyx[0]),x]

        else:
            
            S_r_sub = S_r[y+1:min(y+dyx[0]+1,H-1)]
            
            if "#" in S_r_sub:
                index = calforwordindex(S_r_sub,"#")
                return ["stop",y+index[0]-1,x]
        
            if "*" in S_r_sub:
                index = calforwordindex(S_r_sub,"*")
                return ["stop",y+index[0]-1,x]
        
            if ("#" not in S_r_sub) and ("*" not in S_r_sub) and (y+dyx[0] >= H):
                return ["stop",min(y+dyx[0],H-1),x]
        
        return ["ok",y+dyx[0],x]
            
    else:
    
        if dyx[1] < 0:
            
            S_r_sub = S[y][max(x+dyx[1],0):x]
            
            if "#" in S_r_sub:
                index = calforwordindex(S_r_sub,"#")
                return ["stop",y,x-(len(S_r_sub)-(index[0]+1))]
                
            if "*" in S_r_sub:
                index = calforwordindex(S_r_sub,"*")
                return ["stop",y,x-(len(S_r_sub)-(index[0]+1))]
            
            if ("#" not in S_r_sub) and ("*" not in S_r_sub) and (x+dyx[1] <= -1):
                return ["stop",y,max(0,x+dyx[1])]
        
        else:
            
            S_r_sub = S[y][x+1:min(x+dyx[1]+1,W-1)]
            
            if "#" in S_r_sub:
                index = calforwordindex(S_r_sub,"#")
                return ["stop",y,x+index[0]-1]

            if "*" in S_r_sub:
                index = calforwordindex(S_r_sub,"*")
                return ["stop",y,x+index[0]-1]

            if ("#" not in S_r_sub) and ("*" not in S_r_sub) and (x+dyx[1] >= W):
                return ["stop",y,min(x+dyx[1],W-1)]
    
        return ["ok",y,x+dyx[1]]

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

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: 移動が可能かどうかの判定結果の文字列を格納する変数
    # ny: 次のy座標を示す変数
    # nx: 次のx座標を示す変数
    checkresult,ny,nx = nextposition(y,x,dyx)

    # 考え方4.
    if y < ny:
        y1 = y
        y2 = ny+1
    elif y > ny:
        y1 = ny
        y2 = y+1
    else:
        y1 = 0
        y2 = 0  
    for k in range(y1,y2):
        S[k][x] = "*"

    # 考え方5.
    if x < nx:
        x1 = x
        x2 = nx+1
    elif x > nx:
        x1 = nx
        x2 = x+1
    else:
        x1 = 0
        x2 = 0
    for k in range(x1,x2):
        S[y][k] = "*"
    
    if checkresult != "ok":
        break
    else:
        # 考え方6.
        y = ny
        x = nx

        # 考え方7.
        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
            
            if j < len(td)-1:
                j += 1

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?