Problem: The huge maze The Squares has been newly completed in the famous theme park. Evacuation drills must be conducted under the guidance of the fire department, but the time required for the drills cannot be predicted due to the huge maze. Therefore, you decided to develop an evacuation drill simulator based on the following specifications.

As shown in Fig. 1, the giant maze is represented by W × H squares of horizontal W and vertical H. Each square is either a passage (white square), a wall (brown square), or an emergency exit (green square). The circles in the figure represent people, and the lowercase letters (E, W, S, N) in them represent the direction in which the person is facing (north, south, east, and west). The figure is drawn with the upward direction facing north.


<image>

Figure 1




People in the giant maze initially stand facing either north, south, east, or west. Each person attempts to move in 1-second increments at the same time, following the steps below.

1. Look at the right, front, left, and back squares in the direction you are currently facing, and turn to the first vacant aisle or emergency exit you find. If there is no such square, the direction will not change.
2. If the square in front of you is open and not in front of another person, move it. If there are multiple people with the same square in front of you, the selected one will move in the order of the people in that square, east, north, west, and south.



Those who arrive at the emergency exit after moving will evacuate safely and disappear from the maze.

Create a program that inputs the given huge maze and the location information of people and outputs the time when all people finish evacuating. If it takes more than 180 seconds to escape, output NA. Maze and person location information is given by the characters in rows H and columns W. The meaning of each character is as follows.

: Wall
.: Floor
X: Emergency exit
E: People facing east
N: People facing north
W: People facing west
S: People facing south


The boundary between the maze and the outside is either the wall # or the emergency exit X. In addition, there is always one or more people in the huge maze.



Input

A sequence of multiple datasets is given as input. The end of the input is indicated by two lines of zeros. Each dataset is given in the following format:


W H
str1
str2
::
strH


The first line gives the horizontal size W of the maze and the vertical size H (1 ≤ W, H ≤ 30). The following H line is given the string stri (length W) that represents the i-th line of the maze.

The number of datasets does not exceed 50.

Output

For each input dataset, the time when all people finish evacuating is output on one line.

Examples

Input

10 3
##########
#E.......X
##########
4 4
####
#N.#
#..X
####
5 5
#####
#N..#
###.X
#S..#
#####
6 6
######
#..#X#
#.EE.#
####N#
#....#
######
8 8
##X#####
#....E.#
#####.##
#.#...##
#.W.#..#
#.#.N#.X
#X##.#.#
########
0 0


Output

8
NA
9
16
10


Input

10 3

E.......X

4 4

N.#
..X

5 5

N..#
.X
S..#

6 6

..#X#
.EE.#
N#
....#

8 8
X#####
....E.#
.##
.#...##
.W.#..#
.#.N#.X
X##.#.#

0 0


Output

8
NA
9
16
10

Solution (in JAVA):

Solution:
import java.util.*;
public class Main {
	int [] vx = {1,0,-1,0};
	int [] vy = {0,-1,0,1};
	boolean [] isgoal;
	
	class C{
		int x,y,dir;
		public C(int x, int y, int dir) {
			this.x = x;this.y = y;
			if(dir == 'E')
				dir = 0;
			else if(dir == 'N')
				dir = 1;
			else if(dir == 'S')
				dir = 3;
			else if(dir == 'W')
				dir = 2;
			else{
				
			}
			this.dir = dir;
		}
		public String toString() {
			return "C [x=" + x + ", y=" + y + ", dir=" + dir + "]";
		}
		
	}

	private void doit(){
		Scanner sc=new Scanner(System.in);
		while(true){
			int w = sc.nextInt(), h = sc.nextInt();
			if((w|h) == 0) break;
			char [][] map = new char[h][w];
			ArrayList<C> humlist = new ArrayList<C>();
			for(int i=0; i < h;i++){
				String line = sc.next();
				for(int j=0; j < w;j++){
					char c = line.charAt(j);
					if(c == 'E' || c == 'N' || c == 'W' || c == 'S'){
						humlist.add(new C(j,i,(int)c));
						map[i][j] = '.';
					}
					else{
						map[i][j] = c;
					}
				}
			}
			int step = 0;
			LinkedList<Integer> open = new LinkedList<Integer>();
			open.add(step);
			int len = humlist.size();
			isgoal = new boolean[len];
			boolean isachieve = true;
			while(! open.isEmpty()){
				step = open.removeFirst();
				//debug
				//System.out.println(humlist.toString());
				//change dir
				for(int i = 0; i < len;i++){
					if(isgoal[i])continue;
					C nowhum = humlist.get(i);
					int nowdir = nowhum.dir;
					int tempdir = nowhum.dir;
					boolean changeflg = false;
					for(int j = 0; j < 4; j++){
						nowdir = (j + 4 + nowhum.dir - 1) % 4;
						int xx = nowhum.x + vx[nowdir];
						int yy = nowhum.y + vy[nowdir];
						if(map[yy][xx] == '#') continue;
						if((map[yy][xx] == 'X') || (map[yy][xx] == '.' && ! isin(xx,yy,humlist))){
							changeflg = true;
							break;
						}
					}
					if(changeflg){
						nowhum.dir = nowdir;
					}
					else{
						nowhum.dir = tempdir;
					}
					humlist.set(i, nowhum);
				}
				
				//move
				ArrayList<C> humlistrecord = valueC(humlist);
				for(int i=0; i < len; i++){
					if(isgoal[i]) continue;
					C nowhum = humlist.get(i);
					int xx = nowhum.x + vx[nowhum.dir];
					int yy = nowhum.y + vy[nowhum.dir];
					if(map[yy][xx] == '#' || isin(xx,yy,humlistrecord)) continue;
					int movehum = getmove(xx,yy,humlistrecord);
					if(movehum == i){
						nowhum.x = xx;
						nowhum.y = yy;
						humlist.set(i, nowhum);
					}
				}
				
				//escape
				for(int i = 0; i < len;i++){
					C nowhum = humlist.get(i);
					int humx = nowhum.x, humy = nowhum.y;
					if(map[humy][humx] == 'X'){
						isgoal[i] = true;
					}
				}
				
				//fin
				if(isAllGoal()){
					break;
				}
				if(step + 1 >= 180){
					isachieve = false;
					break;
				}
				open.add(step + 1);
			}
			//debug
			//System.out.println(humlist.toString());
			if(isachieve){
				if(humlist.size() == 0){
					System.out.println(0);
				}
				else{
					System.out.println(step + 1);
				}
				
			}
			else{
				System.out.println("NA");
			}
		}
	}
	
	private boolean isAllGoal(){
		for(int i=0; i < isgoal.length;i++){
			if(! isgoal[i]) return false;
		}
		return true;
	}
	
	private int getmove(int x, int y, ArrayList<C> list){
		for(int i=0; i < 4;i++){
			int xx = x + vx[i];
			int yy = y + vy[i];
			for(int j=0; j < list.size(); j++){
				if(isgoal[j])continue;
				C now = list.get(j);
				boolean cond1 = (xx == now.x && yy == now.y);
				boolean cond2 = ((now.x + vx[now.dir]) == x && (now.y + vy[now.dir]) == y);
				if(cond1 && cond2){
					return j;
				}
			}
		}
		return -1;
	}
	private ArrayList<C> valueC(ArrayList<C> list){
		ArrayList<C> res =  new ArrayList<C>();
		for(int i = 0; i < list.size(); i++){
			C now = list.get(i);
			res.add(new C(now.x, now.y, now.dir));
		}
		return res;
	}
	
	private boolean isin(int x, int y,ArrayList<C> list){
		for(int i=0; i < list.size();i++){
			if(isgoal[i])continue;
			C now = list.get(i);
			if(now.x == x && now.y == y){
				return true;
			}
		}
		return false;
	}


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