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 C++11 (judge verdict: Time Limit Exceeded)

// Template {{{
#include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)
using namespace std;
typedef long long LL;

#ifdef LOCAL
#include "contest.h"
#else
#define dump(x) 
#endif

class range {
    struct Iterator {
        int val, inc;
        int operator*() {return val;}
        bool operator!=(Iterator& rhs) {return val < rhs.val;}
        void operator++() {val += inc;}
    };
    Iterator i, n;
    public:
    range(int e) : i({0, 1}), n({e, 1}) {}
    range(int b, int e) : i({b, 1}), n({e, 1}) {}
    range(int b, int e, int inc) : i({b, inc}), n({e, inc}) {}
    Iterator& begin() {return i;}
    Iterator& end() {return n;}
};

inline bool valid(int x, int w) { return 0 <= x && x < w; }

void iostream_init() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.setf(ios::fixed);
    cout.precision(12);
}
//}}}
bool ismove(char d) {
    const string s = "^v<>";
    for(const char& c : s) if(c == d) return true;
    return false;
}
int dx[4] = {0, 1, 0, -1};
int dy[4] = {-1, 0, 1, 0};
int H, W;
string grid[50];
string prog;

void move(int& x, int& y, int& r, char c) {
    if(c == '^') {
        x += dx[r];
        y += dy[r];
        if(!(valid(x, W) && valid(y, H) && grid[y][x] != '#')) {
            x -= dx[r];
            y -= dy[r];
        }
    } else if(c == 'v') {
        x -= dx[r];
        y -= dy[r];
        if(!(valid(x, W) && valid(y, H) && grid[y][x] != '#')) {
            x += dx[r];
            y += dy[r];
        }
    } else if(c == '<') {
        r = (r + 3) % 4;
    } else if(c == '>') {
        r = (r + 1) % 4;
    } else {
        assert(false);
    }
}

bool check(int x, int y, int r, int& cur) {
    bool posi = true;
    if(prog[cur] == '~') {
        cur++;
        posi = false;
    }
    char c = prog[cur++];
    if(c == 'N') return (r == 0) == posi;
    if(c == 'E') return (r == 1) == posi;
    if(c == 'S') return (r == 2) == posi;
    if(c == 'W') return (r == 3) == posi;
    if(c == 'C') {
        int nx = x + dx[r];
        int ny = y + dy[r];
        assert(valid(nx, W));
        assert(valid(ny, H));
        return (grid[ny][nx] == '#') == posi;
    }
    if(c == 'T') return posi;
    assert(false);
}

map<int, int> memo_close;
map<int, int> memo_open;
int move_to_close(const int cur) {
    if(memo_close.count(cur)) return memo_close[cur];
    char open, close;
    if(prog[cur] == '[') {
        open = '[', close = ']';
    } else if(prog[cur] == '{') {
        open = '{', close = '}';
    } else {
        assert(false);
    }
    int level = 1;
    int i = cur+1;
    for(;; i++) {
        assert(i < prog.size());
        if(prog[i] == close) {
            if(--level == 0) break;
        }
        if(prog[i] == open) level++;
    }
    memo_close[cur] = i;
    memo_open[i] = cur;
    return i;
}
int move_to_open(int cur) {
    assert(memo_open.count(cur));
    return memo_open[cur];
}

int main(){
    iostream_init();
    while(cin >> H >> W) {
        REP(y, H) cin >> grid[y];

        cin >> prog;

        int sx=-1, sy=-1;
        int gx=-1, gy=-1;
        REP(y, H) REP(x, W) {
            if(grid[y][x] == 's') {
                grid[y][x] = '.';
                sx = x, sy = y;
            }
            if(grid[y][x] == 'g') {
                grid[y][x] = '.';
                gx = x, gy = y;
            }
        }

        int x = sx;
        int y = sy;
        int r = 0;
        int cur = 0;
        int res = 0;
        static bool state[1000][50][50][4] = {};
        memset(state, 0, sizeof(state));

        memo_open.clear();
        memo_close.clear();
        REP(i, prog.size()) if(prog[i] == '[' || prog[i] == '{') move_to_close(i); // memorize

        while(true) {
            while(cur < prog.size()) {
                // cout << cur << " " << prog[cur] << endl;
                if(ismove(prog[cur])) {
                    break;
                } else if(prog[cur] == '[') {
                    int open = cur++;
                    bool cond = check(x, y, r, cur);
                    if(!cond) cur = move_to_close(open) + 1;
                } else if(prog[cur] == ']') {
                    cur++;
                } else if(prog[cur] == '{') {
                    int open = cur++;
                    bool cond = check(x, y, r, cur);
                    if(!cond) cur = move_to_close(open) + 1;
                } else if(prog[cur] == '}') {
                    cur = move_to_open(cur);
                } else {
                    assert(false);
                }
            }
            if(cur >= prog.size() || state[cur][y][x][r]) {
                res = -1;
                break;
            }
            state[cur][y][x][r] = true;
            move(x, y, r, prog[cur++]);
            res++;
            if(x == gx && y == gy) {
                break;
            }
        }

        cout << res << endl;
    }
    return 0;
}

/* vim:set foldmethod=marker: */