Problem:


盤面上にロボットと壁，ゴールが設置されており， ロボットの行動パターンを記述したプログラムが与えられる．

与えられるプログラムは以下のEBNF で表される．

プログラム:= {文};
文:= if 文|while 文|動作文;
if 文:= "[", 条件, プログラム, "]";
while 文:= "{", 条件, プログラム, "}";

動作文:= "^"|"v"|"";
条件:= ["~"], "N"|"E"|"S"|"W"|"C"|"T";

「プログラム」は0個以上の「文」からなり，1つ以上の文が存在する場合は 1 つ目の文から順番に1 つずつ文が実行される．「文」は「動作文」，「if 文」，「while 文」のいずれかである．「動作文」は"^", "v","",">" のいずれかであり，それぞれ以下の動作が実行される．

 "^": 前進 

 "v": 後退 

 "": 左に90 度回転 

 ">": 右に90 度回転 

「if 文」は "["，「条件」，「プログラム」，"]" を順番に並べたもので，以下の手順で実行される．

 「条件」の内容が真かどうか判定する 

 判定が真なら「プログラム」の内容を実行し，このif 文の処理を終了する

 判定が偽ならこのif 文の処理を終了する

「while 文」は "{"，「条件」，「プログラム」，"}" を順番に並べたもので，以下の手順で実行される．

 「条件」の内容が真かどうか判定する 

 判定が真なら「プログラム」の内容を実行し，1 に戻る

 判定が偽なら，この while 文の処理を終了する

「条件」は "N", "E", "S", "W", "C", "T" のいずれかであり，先頭には"~" をつけることができる．それぞれの記述は以下の真偽値を表す．

 先頭に "~" が付いている場合は真偽値が逆転 

 N: 北を向いているならば真，そうでなければ偽

 E: 東を向いているならば真，そうでなければ偽

 S: 南を向いているならば真，そうでなければ偽

 W: 西を向いているならば真，そうでなければ偽

 C: 目の前に壁があるならば真，そうでなければ偽

 T: 常に真

ロボットは最初，北を向いているものとする．ロボットは壁を通ることができず，何もないマスのみを移動できる．もし，プログラムが壁の上を通るような動作を実行しようとした場合，ロボットは移動せずその場にとどまる．最後に，ロボットはゴールに到達した時，実行途中のプログラムが残っていたとしてもすべて中断して動作を停止する．

このとき，ロボットがゴールにたどり着くまでにどのぐらい時間がかかるのか知りたい．ロボットは条件判定やプログラムの読み込みに関しては非常に高速に実行できるので実際の動作時間を決定するのは「動作文」のみである．そこで，このロボットがゴールに辿り着くまでに「動作文」を何回実行するかを教えてほしい．

なお，壁の上を通るような動作を実行しようとして，実際には「動作文」の動作が行われなかった場合にも「動作文」は実行されたものとみなす．

Input

入力は以下の形式で与えられる．

H W
a1,1a1,2 . . . a1,W
a2,1a2,2 . . . a2,W
: : :
aH,1aH,2 . . . aH,W
s

H は盤面の高さ，W は盤面の幅を表す．

次に盤面を真上から見た状態が与えられる．この盤面は上，下，左，右がそれぞれ北，南，西，東に対応する．各マスの状態を表す ai,j は以下のいずれかの文字である．

 "s" : ロボット（ロボットの初期位置．このマスには壁がないことが保証されている）

 "g" : ゴール

 "#" : 壁（ロボットは壁の上を移動することはできない）

 "." : 何もないマス

s にはロボットに与えられるプログラムが文字列として入力される．

Constraints

 1 ≤  H,W ≤ 50

 1 ≤ s の文字数 ≤ 1,000

 ai,j は".", "#", "s", "g" のいずれか

 "s", "g" はそれぞれ 1 回しか登場しない

 i = 1 または i = H または j = 1 または j = W ならば ai,j = "#"（盤面の外周は壁で囲まれていることが保証されている）

 s として与えられるプログラムは構文的に正しい

Output

たどり着ける場合は"到達するまでに実行した「動作文」の数" を，たどりつけない場合は "-1" を出力せよ．なお，壁の上を通るような動作を実行しようとして，実際には「動作文」の動作が行われなかった場合にも「動作文」が実行されたものとみなす点に注意せよ（入力例1）．

Sample Input 1

5 3
###
#g#
#.#
#s#
###
^<^<vv

Output for the Sample Input 1

5

Sample Input 2

5 7
#######
#.#g..#
#.###.#
#s....#
#######
{T{~C^}<}

Output for the Sample Input 2

17

Sample Input 3

5 7
#######
#.#g..#
#.###.#
#s....#
#######
{T{~C^}>}

Output for the Sample Input 3

-1



Sample input:
5 3
###
#g#
#.#
#s#
###
^<^<vv


Sample output:
5

Submission status: Accepted

Solution code:
def main():
    H, W = map(int, input().split())
    MP = [input() for i in range(H)]
    for i in range(H):
        mi = MP[i]
        for j in range(W):
            c = mi[j]
            if c == 's':
                sx = j; sy = i
            elif c == 'g':
                gx = j; gy = i
    S = input()
    L = len(S)
    X = [-1]*len(S)
    st = []
    for i, c in enumerate(S):
        if c in "[{":
            st.append(i)
        elif c in "]}":
            k = st.pop()
            X[k] = i
            X[i] = k
    ds = "WNES"
    dd = ((-1, 0), (0, -1), (1, 0), (0, 1))
    U = set()
    ans = 0
    d = 1
    cur = 0
    def check(c, x, y, d):
        if c == "T":
            return 1
        if c in ds:
            return (d == ds.index(c))
        dx, dy = dd[d]
        return MP[y+dy][x+dx] == "#"
    x = sx; y = sy
    ok = 0
    while 1:
        if x == gx and y == gy:
            ok = 1
            break
        br = 0
        while cur < L:
            key = (x, y, d, cur)
            if key in U:
                br = 1
                break
            U.add(key)

            c = S[cur]
            if c in "[{":
                c = S[cur+1]
                if c == '~':
                    if not check(S[cur+2], x, y, d):
                        cur += 3
                    else:
                        cur = X[cur]+1
                else:
                    if check(c, x, y, d):
                        cur += 2
                    else:
                        cur = X[cur]+1
            elif c == "]":
                cur += 1
            elif c == "}":
                cur = X[cur]
            else:
                break
        if cur == L or br:
            break
        c = S[cur]
        dx, dy = dd[d]
        assert c in "<>^v"
        if c == "^":
            if MP[y+dy][x+dx] != '#':
                x += dx; y += dy
        elif c == "v":
            if MP[y-dy][x-dx] != '#':
                x -= dx; y -= dy
        elif c == "<":
            d = (d - 1) % 4
        else: # c == ">"
            d = (d + 1) % 4
        cur += 1
        ans += 1
    if ok:
        print(ans)
    else:
        print(-1)
main()

Submission status: Runtime Error

Solution code:
def parse_prog(prog, pointer, level, code):
  while True:
    pointer, code = parse_sent(prog, pointer, level, code)
    if pointer == len(prog):break
    if prog[pointer] in ("]", "}"):break
  return pointer + 1, code

def parse_sent(prog, pointer, level, code):
  head = prog[pointer]
  if head == "[":
    pointer, code = parse_if(prog, pointer, level, code)
  elif head == "{":
    pointer, code = parse_while(prog, pointer, level, code)
  else:
    pointer, code = parse_behave(prog, pointer, level, code)
  return pointer, code

def parse_if(prog, pointer, level, code):
  pointer += 1
  head = prog[pointer]
  cond, pointer = parse_cond(prog, pointer)
  code += ("  " * level + "if ({}):\n").format(cond)
  pointer, code = parse_prog(prog, pointer, level + 1, code)
  return pointer, code

def parse_cond(prog, pointer):
  head = prog[pointer]
  if head == "~":
    cond = prog[pointer:pointer+2]
    pointer += 2
  else:
    cond = prog[pointer:pointer+1]
    pointer += 1
  cond = cond_convert(cond)
  return cond, pointer

def parse_while(prog, pointer, level, code):
  pointer += 1
  cond, pointer = parse_cond(prog, pointer)
  tab0 = "  " * level
  tab1 = tab0 + "  "
  tab2 = tab1 + "  "
  code += tab0 + "STATUS += 1\n"
  code += tab0 + "while ({}):\n".format(cond)
  code += tab1 + "if (STATUS, DIRECT, X, Y) in DIC:\n"
  code += tab2 + "print(-1)\n"
  code += tab2 + "return -1\n"
  code += tab1 + "else:\n"
  code += tab2 + "DIC[(STATUS, DIRECT, X, Y)] = True\n"
  pointer, code = parse_prog(prog, pointer, level + 1, code)
  code += ("  " * level + "STATUS -= 1" + "\n")
  return pointer, code

def parse_behave(prog, pointer, level, code):
  behave = prog[pointer]
  behave = convert_behave(behave, level)
  code += behave
  return pointer + 1, code

def cond_convert(cond):
  if cond == "~T":return "False"
  if cond == "T": return "True"
  ret = ""
  if cond[0] == "~":ret += "not "
  if cond[-1] in ("N", "E", "S", "W"):
    return ret + ("DIRECT == {}").format(cond[-1])
  if cond[-1] == "C":
    return ret + "FRONT == \"#\""
  if cond[-1] == "T":
    return ret + "True"

def convert_behave(behave, level):
  tab = "  " * level
  tab2 = tab + "  "
  ret = ""
  ret += tab + "if (X, Y) == (GX, GY):"
  ret += "\n" + tab2 + "print(CNT)"
  ret += "\n" + tab2 + "return CNT"
  if behave == "^":
    ret += "\n" + tab + "DX, DY = VEC[DIRECT]"
    ret += "\n" + tab + "NX, NY = X + DX, Y + DY"
    ret += "\n" + tab + "if MP[NY][NX] != \"#\":"
    ret += "\n" + tab2 + "X, Y = NX, NY"
    ret += "\n" + tab2 + "FRONT = MP[NY + DY][NX + DX]"
  if behave == "v":
    ret += "\n" + tab + "DX, DY = VEC[DIRECT]"
    ret += "\n" + tab + "NX, NY = X - DX, Y - DY"
    ret += "\n" + tab + "if MP[NY][NX] != \"#\":"
    ret += "\n" + tab2 + "X, Y = NX, NY"
    ret += "\n" + tab2 + "FRONT = MP[NY + DY][NX + DX]"
  if behave == ">":
    ret += "\n" + tab + "DIRECT = (DIRECT + 1) % 4"
    ret += "\n" + tab + "DX, DY = VEC[DIRECT]"
    ret += "\n" + tab + "FRONT = MP[Y + DY][X + DX]"
  if behave == "<":
    ret += "\n" + tab + "DIRECT = (DIRECT - 1) % 4"
    ret += "\n" + tab + "DX, DY = VEC[DIRECT]"
    ret += "\n" + tab + "FRONT = MP[Y + DY][X + DX]"
  ret += "\n" + tab + "CNT += 1\n"
  return ret

h, w = map(int, input().split())
MP = [input() for _ in range(h)]
for y in range(h):
  for x in range(w):
    if MP[y][x] == "s":
      X, Y = x, y
      FRONT = MP[y - 1][x]
    if MP[y][x] == "g":
      GX, GY = x, y
DIC = {}
VEC = ((0, -1), (1, 0), (0, 1), (-1, 0))
DIRECT = 0
STATUS = 0
CNT = 0
PROGRAM = "def main(MP, X, Y, GX, GY, FRONT, DIC, VEC, DIRECT, STATUS, CNT):\n" + parse_prog(input(), 0, 1, "")[1] + "main(MP, X, Y, GX, GY, FRONT, DIC, VEC, DIRECT, STATUS, CNT)"

exec(PROGRAM)