#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

vector<string> g;
struct Cell {
    int path_to_c, c_id, in_id;
    Cell() : path_to_c(-1), c_id(0), in_id(-1) {}
};
vector<vector<Cell>> v;
vector<int> cycle_len = { 0 };
int next_cycle = 1;

inline bool robot_on(int y, int x) {
    return 'A' <= g[y][x] && g[y][x] <= 'Z';
}

inline void getdest(int y, int x, int &yy, int &xx) {
    switch(g[y][x]) {
    case 'e':
    case 'E':
        yy = y; xx = x+1;
        break;
    case 'W':
    case 'w':
        yy = y; xx = x-1;
        break;
    case 'S':
    case 's':
        yy = y+1; xx = x;
        break;
    case 'N':
    case 'n':
        yy = y-1; xx = x;
        break;
    default:
        assert(false);
    }
}

inline int follow_cycle(int y, int x) {
    int a = 0;
    int yy = y, xx = x;
    do {
        v[yy][xx].path_to_c = 0;
        v[yy][xx].in_id = a;
        ++a;
        getdest(yy, xx, yy, xx);
    } while(yy != y || xx != x);
    return a;
}

inline int dfs(int y, int x) {
    if(v[y][x].c_id > 0) {
        return v[y][x].c_id;
    }
    if(v[y][x].c_id == -1) {
        cycle_len.push_back(follow_cycle(y, x));
        return v[y][x].c_id = next_cycle++;
    }
    int yy, xx;
    getdest(y, x, yy, xx);
    v[y][x].c_id = -1;
    int ans = v[y][x].c_id = dfs(yy, xx);
    if(v[y][x].path_to_c == -1)
        v[y][x].path_to_c = 1+v[yy][xx].path_to_c;
    if(v[y][x].in_id == -1)
        v[y][x].in_id = v[yy][xx].in_id;
    return ans;
}

struct Ans {
    int i, j, t;
    Ans(int i, int j, int t) : i(i), j(j), t(t) {}
};

int main() {
    #define FNAME "robots"
    #ifndef LOCAL
    freopen(FNAME ".in", "r", stdin);
    freopen(FNAME ".out", "w", stdout);
    #endif
    int n, m, ggg;
    cin >> n >> m >> ggg;
    g.resize(n);
    for(int i = 0; i < n; ++i) {
        cin >> g[i];
    }
    v.assign(n, vector<Cell>(m));
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            if(v[i][j].c_id == 0) {
                dfs(i, j);
            }
        }
    }
    vector<int> re(cycle_len.size()), nxt(cycle_len.size());
    vector<Ans> ans;
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            if(robot_on(i, j)) {
                int c = v[i][j].c_id;
                if(re[c] < cycle_len[c]) {
                    int t = (v[i][j].path_to_c + cycle_len[c] - v[i][j].in_id) % cycle_len[c];
                    int t_ans = (nxt[c] - t) % cycle_len[c];
                    if(t_ans < 0) t_ans += cycle_len[c];
                    ans.push_back(Ans(i, j, t_ans));
                    ++re[c];
                    ++nxt[c];
                }
            }
        }
    }
    printf("%d\n", (int)ans.size());
    if(ggg) {
        for(const Ans &a : ans) {
            printf("%d %d %d\n", a.i+1, a.j+1, a.t+1);
        }
    }
    /*cycle.assign(n, vector<int>(m));
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            if(cycle[i][j] == 0) {
                dfs(i, j);
            }
        }
    }
    vector<int> rpc(cycle_len.size());
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            if(robot_on(i, j)) {
                rpc[cycle[i][j]]++;
            }
        }
    }
    int ans = 0;
    int sz = cycle_len.size();
    for(int i = 1; i < sz; ++i) {
        ans += min(cycle_len[i], rpc[i]);
    }
    cout << ans;*/
    return 0;
}
