p01755 AI_16170
A robot, a wall, and a goal are installed on the board, and a program that describes the behavior pattern of the robot is given.

The given program is represented by the following EBNF.


Program: = {statement};
Statement: = if statement | while statement | action statement;
if statement: = "[", condition, program, "]";
while statement: = "{", condition, program, "}";

Action statement: = "^" | "v" | "<" | ">";
Condition: = ["~"], "N" | "E" | "S" | "W" | "C" | "T";


A "program" consists of 0 or more "sentences", and if there is one or more sentences, the sentences are executed one by one in order from the first sentence. A "statement" is one of an "action statement", an "if statement", and a "while statement". The "action statement" is one of "^", "v", "<", ">", and the following actions are executed respectively.

* "^": Advance
* "v": Retreat
* "<": Rotate 90 degrees to the left
* ">": Rotate 90 degrees to the right



The "if statement" is an arrangement of "[", "condition", "program", "]" in order, and is executed by the following procedure.

1. Determine if the content of the "condition" is true
2. If the judgment is true, execute the contents of the "program" and end the processing of this if statement.
3. If the judgment is false, the processing of this if statement ends.



A "while statement" is an arrangement of "{", "condition", "program", and "}" in order, and is executed by the following procedure.

1. Determine if the content of the "condition" is true
2. If the judgment is true, execute the contents of "Program" and return to 1.
3. If the judgment is false, the processing of this while statement ends.



The "condition" is one of "N", "E", "S", "W", "C", "T", and can be prefixed with "~". Each description represents the following boolean values.

* If "~" is added at the beginning, the boolean value is reversed.
* N: True if facing north, false otherwise
* E: True if facing east, false otherwise
* S: True if facing south, false otherwise
* W: True if facing west, false otherwise
* C: True if there is a wall in front of you, false otherwise
* T: Always true



It is assumed that the robot is initially facing north. Robots cannot pass through walls and can only move empty squares. If the program tries to perform an action that passes over a wall, the robot will not move and will stay in place. Finally, when the robot reaches the goal, it interrupts all the programs that are being executed, even if they remain, and stops the operation.

At this time, I would like to know how long it will take for the robot to reach the goal. Since the robot can execute condition judgment and program loading at a very high speed, it is only the "action statement" that determines the actual operation time. Therefore, please tell me how many times this robot executes the "motion statement" before reaching the goal.

It is considered that the "action statement" has been executed even if the action of the "action statement" is not actually performed when trying to execute an action that passes over the wall.

Constraints

* 1 ≤ H, W ≤ 50
* 1 ≤ s number of characters ≤ 1,000
* ai, j is one of ".", "#", "S", "g"
* "s" and "g" appear only once each
* If i = 1 or i = H or j = 1 or j = W, then ai, j = "#" (the outer circumference of the board is guaranteed to be surrounded by a wall)
* The program given as s is syntactically correct

Input

The input is given in the following format.


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


H is the height of the board and W is the width of the board.

Next, the state of the board viewed from directly above is given. The top, bottom, left, and right of this board correspond to north, south, west, and east, respectively. Ai and j, which represent the state of each cell, are one of the following characters.

* "s": Robot (robot initial position. This square is guaranteed to have no walls)
* "g": Goal
* "#": Wall (Robots cannot move on the wall)
* ".": An empty square



The program given to the robot is input as a character string in s.

Output

If you can reach it, output "the number of" action statements "executed before reaching it". If you cannot reach it, output "-1". In addition, when trying to execute an action that passes over a wall, " Note that even if the action of the "action statement" is not performed, it is considered that the "action statement" has been executed (input example 1).

Examples

Input

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


Output

5


Input

5 3

g#
.#
s#

^<^<vv


Output

5


Input

5 7

.#g..#
.###.#
s....#

{T{~C^}<}


Output

17


Input

5 7

.#g..#
.###.#
s....#

{T{~C^}>}


Output

-1
import java.awt.geom.Point2D;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;

public class Main {
  final static int INF = 1 << 28;
  final static long MOD = 1_000_000_007;
  final static double EPS = 1e-9;
  final static double GOLDEN_RATIO = (1.0 + Math.sqrt(5)) / 2.0;
  Scanner sc = new Scanner(System.in);

  public static void main(String[] args) {
    new Main().run();
  }

  static int[][] ofs = {
      {0, -1},
      {1, 0},
      {0, 1},
      {-1, 0}
  };

  static int min = INF;
  static int count = 0;

  static class State implements Comparable<State> {
    int x, y;
    int dir;

    final static State[][][] LUT;

    private State(int x, int y, int dir) {
      this.x = x;
      this.y = y;
      this.dir = dir;
    }

    static State valueOf(int x, int y, int dir) {
      if (field[y][x] == 'g') {
        min = Math.min(min, count);
      }
      return LUT[x][y][dir];
    }

    static {
      State[][][] table = new State[50][50][4];
      for (int i = 0; i < 50; ++i) {
        for (int j = 0; j < 50; ++j) {
          for (int k = 0; k < 4; ++k) {
            table[i][j][k] = new State(i, j, k);
          }
        }
      }
      LUT = table;
    }

    State next(char c) {
      switch (c) {
        case '^':
          if (is('C')) {
            return this;
          } else {
            return valueOf(x + ofs[dir][0], y + ofs[dir][1], dir);
          }
        case 'v':
          if (is('D')) {
            return this;
          } else {
            return valueOf(x + ofs[(dir + 2) % 4][0], y + ofs[(dir + 2) % 4][1], dir);
          }
        case '<':
          return valueOf(x, y, (dir - 1 + 4) % 4);
        case '>':
          return valueOf(x, y, (dir + 1) % 4);
        default:
          assert false;
          return null;
      }
    }

    boolean is(char c) {
      switch (c) {
        case 'N':
          return dir == 0;
        case 'E':
          return dir == 1;
        case 'S':
          return dir == 2;
        case 'W':
          return dir == 3;
        case 'C':
          return field[y + ofs[dir][1]][x + ofs[dir][0]] == '#';
        case 'D':
          return field[y + ofs[(dir + 2) % 4][1]][x + ofs[(dir + 2) % 4][0]] == '#';
        default:
          return true;
      }
    }

    boolean is(String s) {
      if (s.length() == 1) {
        return is(s.charAt(0));
      } else {
        return !is(s.charAt(1));
      }
    }

    @Override
    public int compareTo(State s) {
      if (x != s.x) {
        return x - s.x;
      }
      if (y != s.y) {
        return y - s.y;
      }
      return dir - s.dir;
    }
  }

  int h, w;
  static char[][] field;
  String s;

//  TreeSet<Ret> done = new TreeSet<>();

  boolean isIf(int index) {
    return s.charAt(index) == '[';
  }

  boolean isWhile(int index) {
    return s.charAt(index) == '{';
  }

  boolean isCmd(int index) {
    switch (s.charAt(index)) {
      case '^':
      case 'v':
      case '<':
      case '>':
        return true;
      default:
        return false;
    }
  }

  String jouken(int index) {
    if (s.charAt(index) == '~') {
      return "" + s.charAt(index) + s.charAt(index + 1);
    } else {
      return "" + s.charAt(index);
    }
  }

  class Ret implements Comparable<Ret> {
    int index;
    State state;

    Ret(int i, State s) {
      index = i;
      state = s;
    }

    @Override
    public int compareTo(Ret d) {
      if (index != d.index) {
        return index - d.index;
      }
      return state.compareTo(d.state);
    }
  }

  Ret bun(int index, State state) {
    if (isIf(index)) {
      ++index;
      String jouken = jouken(index);
      index += jouken.length();
      if (state.is(jouken)) {
        Ret ret = program(index, state);
        if (ret == null) {
          return null;
        }
        state = ret.state;
      }
      int indent = 0;
      for (; ; ) {
        if (s.charAt(index) == '[') {
          ++indent;
        }
        if (s.charAt(index) == ']') {
          if (indent == 0) {
            break;
          }
          --indent;
        }
        ++index;
      }
      ++index;
      return new Ret(index, state);
    } else if (isWhile(index)) {
      ++index;
      String jouken = jouken(index);
      index += jouken.length();
      while (state.is(jouken)) {
        Ret ret = program(index, state);
        if (ret == null) {
          return null;
        }
        state = ret.state;
      }
      int indent = 0;
      for (; ; ) {
        if (s.charAt(index) == '{') {
          ++indent;
        }
        if (s.charAt(index) == '}') {
          if (indent == 0) {
            break;
          }
          --indent;
        }
        ++index;
      }
      ++index;
      return new Ret(index, state);
    } else {
      assert isCmd(index);
      char cmd = s.charAt(index);
      ++index;
      ++count;
      state = state.next(cmd);
      return new Ret(index, state);
    }
  }

  Ret program(int index, State state) {
//    Ret init = new Ret(index, state);
//    if (done.contains(init)) {
//      return null;
//    }
//    done.add(init);
    while (index < s.length()) {
      if (done[index][state.y][state.x][state.dir]) {
        return null;
      }
      done[index][state.y][state.x][state.dir] = true;
      char c = s.charAt(index);
      if (c == ']' || c == '}') {
        return new Ret(index + 1, state);
      }
      Ret ret = bun(index, state);
      if (ret == null) {
        return null;
      }
//      if (done.contains(ret)) {
//        return null;
//      }
//      done.add(ret);
      index = ret.index;
      state = ret.state;
    }
    return new Ret(index, state);
  }

  boolean[][][][] done;

  void run() {
    h = ni();
    w = ni();
    field = new char[h][w];
    State init = null;
    for (int i = 0; i < h; ++i) {
      String str = sc.next();
      for (int j = 0; j < w; ++j) {
        field[i][j] = str.charAt(j);
        if (field[i][j] == 's') {
          init = State.valueOf(j, i, 0);
        }
      }
    }
    s = sc.next();
    done = new boolean[s.length()][h][w][4];
    program(0, init);
    System.out.println(min == INF ? -1 : min);
  }

  int ni() {
    return Integer.parseInt(sc.next());
  }

  void debug(Object... os) {
    System.err.println(Arrays.deepToString(os));
  }
}