#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
#define MAXN 50
char map[MAXN][MAXN];
bool visited[MAXN][MAXN][MAXN][MAXN];
struct node {
int x1;
int y1;
int x2;
int y2;
string s;
};
node start;
queue<node> q;
int N, M;
string dir = "EWSN";
int dx[] = { 0,0,1,-1 };
int dy[] = { 1,-1,0,0 };
bool is_range(int x, int y) {
return (x >= 0 && y >= 0 && x < N && y < M);
}
pair<int,int> change_dir(int x, int y, int d) {
if (d == 0) return { x,0 };
else if (d == 1) return { x, M - 1 };
else if (d == 2) return { 0,y };
return { N - 1,y };
}
string bfs() {
q.push(start);
visited[start.x1][start.y1][start.x2][start.y2] = true;
while (!q.empty()) {
int q_size = q.size();
while (q_size--) {
int x1 = q.front().x1;
int y1 = q.front().y1;
int x2 = q.front().x2;
int y2 = q.front().y2;
string s = q.front().s;
if (x1 == x2 && y1 == y2) return s;
q.pop();
for (int k = 0; k < 4; k++) {
int nx1 = x1 + dx[k];
int ny1 = y1 + dy[k];
int nx2 = x2 + dx[k];
int ny2 = y2 + dy[k];
if (!is_range(nx1, ny1)) {
pair<int, int> tmp = change_dir(nx1, ny1, k);
nx1 = tmp.first;
ny1 = tmp.second;
}
if (!is_range(nx2, ny2)) {
pair<int, int> tmp = change_dir(nx2, ny2, k);
nx2 = tmp.first;
ny2 = tmp.second;
}
if (map[nx1][ny1] == 'G' || map[nx2][ny2] == 'G') continue;
if (map[nx1][ny1] == 'X') {
nx1 = x1;
ny1 = y1;
}
if (map[nx2][ny2] == 'X') {
nx2 = x2;
ny2 = y2;
}
if (visited[nx1][ny1][nx2][ny2]) continue;
visited[nx1][ny1][nx2][ny2] = true;
q.push({ nx1,ny1,nx2,ny2,s + dir[k] });
}
}
}
return "-1";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while (t--) {
while (!q.empty()) q.pop();
start = { -1,-1,-1,-1,"" };
memset(visited, false, sizeof(visited));
cin >> N >> M;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> map[i][j];
if (map[i][j] == 'P') {
if (start.x1 == -1) start.x1 = i, start.y1 = j;
else start.x2 = i, start.y2 = j;
map[i][j] = '.';
}
}
}
string ans = bfs();
if (ans == "-1") cout << "IMPOSSIBLE\n";
else cout << ans.length() << " " << ans << "\n";
}
return 0;
}