package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
in := bufio.NewReaderSize(os.Stdin, 1<<20)
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
var R, C int
fmt.Fscan(in, &R, &C)
rowLists := make([][]int, R)
colLists := make([][]int, C)
types := make([]byte, 0)
for r := 0; r < R; r++ {
var s string
fmt.Fscan(in, &s)
for c := 0; c < C; c++ {
if s[c] != '.' {
id := len(types)
types = append(types, s[c])
rowLists[r] = append(rowLists[r], id)
colLists[c] = append(colLists[c], id)
}
}
}
M := len(types)
left := make([]int, M)
right := make([]int, M)
up := make([]int, M)
down := make([]int, M)
for i := 0; i < M; i++ {
left[i], right[i], up[i], down[i] = -1, -1, -1, -1
}
for r := 0; r < R; r++ {
arr := rowLists[r]
for i, id := range arr {
if i > 0 {
left[id] = arr[i-1]
}
if i+1 < len(arr) {
right[id] = arr[i+1]
}
}
}
for c := 0; c < C; c++ {
arr := colLists[c]
for i, id := range arr {
if i > 0 {
up[id] = arr[i-1]
}
if i+1 < len(arr) {
down[id] = arr[i+1]
}
}
}
const (
N = 0
E = 1
S = 2
W = 3
)
reflSlash := [4]int{W, S, E, N}
reflBack := [4]int{E, N, W, S}
opp := [4]int{S, W, N, E}
nextState := make([]int, M*4)
for m := 0; m < M; m++ {
for inSide := 0; inSide < 4; inSide++ {
var outSide int
if types[m] == '/' {
outSide = reflSlash[inSide]
} else {
outSide = reflBack[inSide]
}
nm := -1
switch outSide {
case N:
nm = up[m]
case E:
nm = right[m]
case S:
nm = down[m]
case W:
nm = left[m]
}
if nm == -1 {
nextState[m*4+inSide] = -1
} else {
nextState[m*4+inSide] = nm*4 + opp[outSide]
}
}
}
entries := make([]string, 0, 2*(R+C))
starts := make([]int, 0, 2*(R+C))
for c := 0; c < C; c++ {
entries = append(entries, "N"+strconv.Itoa(c+1))
if len(colLists[c]) == 0 {
starts = append(starts, -1)
} else {
starts = append(starts, colLists[c][0]*4+N)
}
}
for c := 0; c < C; c++ {
entries = append(entries, "S"+strconv.Itoa(c+1))
if len(colLists[c]) == 0 {
starts = append(starts, -1)
} else {
arr := colLists[c]
starts = append(starts, arr[len(arr)-1]*4+S)
}
}
for r := 0; r < R; r++ {
entries = append(entries, "E"+strconv.Itoa(r+1))
if len(rowLists[r]) == 0 {
starts = append(starts, -1)
} else {
arr := rowLists[r]
starts = append(starts, arr[len(arr)-1]*4+E)
}
}
for r := 0; r < R; r++ {
entries = append(entries, "W"+strconv.Itoa(r+1))
if len(rowLists[r]) == 0 {
starts = append(starts, -1)
} else {
starts = append(starts, rowLists[r][0]*4+W)
}
}
stateSeen := make([]int, M*4)
mirrorSeen := make([]int, M)
ans := make([]string, 0)
for i, start := range starts {
if start == -1 {
continue
}
sim := i + 1
count := 0
s := start
for s != -1 && stateSeen[s] != sim {
stateSeen[s] = sim
m := s >> 2
if mirrorSeen[m] != sim {
mirrorSeen[m] = sim
count++
}
s = nextState[s]
}
if count == M {
ans = append(ans, entries[i])
}
}
fmt.Fprintln(out, len(ans))
if len(ans) > 0 {
for i, s := range ans {
if i > 0 {
fmt.Fprint(out, " ")
}
fmt.Fprint(out, s)
}
fmt.Fprintln(out)
}
}