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

Solution in JAVA (judge verdict: Memory Limit Exceeded)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

import static java.lang.Integer.parseInt;

/**
 * AI
 */
public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String line;

		Main main = new Main();

		while ((line = br.readLine()) != null && !line.isEmpty()) {

			int H, W;
			H = parseInt(line.substring(0, line.indexOf(' ')));
			W = parseInt(line.substring(line.indexOf(' ') + 1));

			char[][] map = new char[H][W];
			for (int i = 0; i < H; i++) {
				line = br.readLine();
				for (int j = 0; j < W; j++) {
					map[i][j] = line.charAt(j);
				}
			}

			String prg = br.readLine();

			//solve
			Robot robot = main.new Robot(map, prg);
			robot.run();

			System.out.println(robot.elapsed);
		}
	} //end while

	class Robot {
		private final int[] DIRS = new int[]{0, 1, 2, 3};//N, E, S, W
		private final int N = DIRS[0];
		private final int E = DIRS[1];
		private final int S = DIRS[2];
		private final int W = DIRS[3];
		private final int[][] FORWARD = new int[][]{{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
		private final int[][] BACKWARD = new int[][]{{1, 0}, {0, -1}, {-1, 0}, {0, 1}};

		//
		char[][] map;
		String prg;
		int prgEnd;
		int y, x;
		int gy, gx;
		int dir;
		int elapsed = 0;

		Robot(char[][] map, String prg) {
			this.map = map;
			this.prg = prg;
			for (int i = 0; i < map.length; i++) {
				for (int j = 0; j < map[0].length; j++) {
					if (map[i][j] == 's') {
						y = i;
						x = j;
					} else if (map[i][j] == 'g') {
						gy = i;
						gx = j;
					}
				}
			}
			this.dir = N;
		}

		void run() {
			prgEnd = prg.length();
			sub(prg);
		}

		void sub(String sub) {

			if (elapsed == -1) return;

			int ptr = 0;
			for (; ptr < sub.length(); ptr++) {
				char code = sub.charAt(ptr);
				switch (code) {
					//action
					case '^':
					case 'v':
					case '<':
					case '>':
						action(code);
						break;
					//control
					case '[':
					case '{':
						int _ptr1, _ptr2 = ptr + 1;
						String condStr = "";
						boolean condRes = false;

						condStr += sub.charAt(_ptr2);
						if (sub.charAt(_ptr2) == '~') {
							_ptr2++;
							condStr += sub.charAt(_ptr2);
						}
						_ptr2++;
						_ptr1 = _ptr2;
						condRes = cond(condStr);

						Deque<Character> stack = new ArrayDeque<>();
						stack.offer(code);
						while (!stack.isEmpty()) {
							char _code = sub.charAt(_ptr2);
							switch (_code) {
								case '[':
								case '{':
									stack.offer(_code);
									break;
								case ']':
								case '}':
									stack.pollLast();
									break;
							}
							_ptr2++;
						}
						_ptr2--;
						if (condRes) {
							if (code == '[') {
								sub(sub.substring(_ptr1, _ptr2));
							} else if (code == '{') {
								int _y, _x, _dir;
								_y = y;
								_x = x;
								_dir = dir;
								while (condRes) {
									sub(sub.substring(_ptr1, _ptr2));
									condRes = cond(condStr);
									if (y == gy && x == gx) {
										break;
									}
									if (y == _y && x == _x && dir == _dir && condRes) {
										elapsed = -1;
										break;
									}
								}
							}
						}
						ptr = _ptr2;
						break;
				}
				if (y == gy && x == gx) break;
			}

			if (ptr == prgEnd) elapsed = -1;
		}

		void action(char action) {
			switch (action) {
				case '^':
					if (!cond("C")) {
						y += FORWARD[dir][0];
						x += FORWARD[dir][1];
					}
					break;
				case 'v':
					if (!cond("B")) {
						y += BACKWARD[dir][0];
						x += BACKWARD[dir][1];
					}
					break;
				case '<'://L
					dir = (dir - 1 + 4) % 4;
					break;
				case '>'://R
					dir = (dir + 1) % 4;
					break;
			}
			elapsed++;
		}

		boolean cond(String cond) {
			boolean ret = false;
			switch (cond.charAt(cond.length() - 1)) {
				case 'N':
					if (dir == N) ret = true;
					break;
				case 'E':
					if (dir == E) ret = true;
					break;
				case 'S':
					if (dir == S) ret = true;
					break;
				case 'W':
					if (dir == W) ret = true;
					break;
				case 'C':
					int fy = y + FORWARD[dir][0];
					int fx = x + FORWARD[dir][1];
					if (map[fy][fx] == '#') ret = true;
					break;
				case 'B':
					int by = y + BACKWARD[dir][0];
					int bx = x + BACKWARD[dir][1];
					if (map[by][bx] == '#') ret = true;
					break;
				case 'T':
					ret = true;
					break;
			}
			if (cond.charAt(0) == '~') {
				ret = !ret;
			}
			return ret;
		}
	}
} //end main