#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:256000000")

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <cassert>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define TASK "robots"
#define forn(i, n) for(int i = 0; i < (int)(n); i++)
#define for1(i, n) for(int i = 1; i <= (int)(n); i++)
#define mk make_pair
#define pk push_back
#define all(v) v.begin(), v.end()

const int MAXN = 1007;
const int di[4] = { -1, 0, 1, 0 };
const int dj[4] = { 0, 1, 0, -1 };

int solve();

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);
#else
	freopen(TASK".in", "r", stdin), freopen(TASK".out", "w", stdout);
#endif
	return solve();
}

struct pt {
	int i, j;
};

struct stans {
	int i, j, t;
};

int n, m, g, cycles, curcyc;
char c[MAXN][MAXN];
int used[MAXN][MAXN];
int num[MAXN][MAXN], to[MAXN][MAXN], len[MAXN * MAXN], dist[MAXN][MAXN], period[MAXN][MAXN], sqr[MAXN * MAXN];

vector<pt> st, can[MAXN * MAXN];
pt topt[MAXN][MAXN];
vector<pt> order[MAXN * MAXN];

int large(int i, int j) {
	return c[i][j] == 'N' || c[i][j] == 'E' || c[i][j] == 'S' || c[i][j] == 'W';
}

int get(int i, int j) {
	char x = c[i][j];
	if (x == 'N' || x == 'n') return 0;
	if (x == 'E' || x == 'e') return 1;
	if (x == 'S' || x == 's') return 2;
	if (x == 'W' || x == 'w') return 3;
}

int sq(int z1, int z2) {
	if (z1 < 0) return 0;

	int i1 = st[z1].i, j1 = st[z1].j;
	int i2 = st[z2].i, j2 = st[z2].j;

	return (j2 - j1) * i1;
}

void dfs(int i, int j) {
	used[i][j] = 1;
	st.pk({ i, j });

	int w = get(i, j);
	int ni = i + di[w], nj = j + dj[w];
	
	if (used[ni][nj] == 1) {
		cycles++;
		curcyc = cycles;

		for (int z = (int)(st.size()) - 1, per = 0; z >= 0; z--, per++) {
			len[cycles]++;
			
			int bi = st[z].i, bj = st[z].j;
			
			order[cycles].pk({ bi, bj });

			to[bi][bj] = num[bi][bj] = cycles;
			period[bi][bj] = per;
			topt[bi][bj] = { bi, bj };

			sqr[cycles] += sq(z - 1, z);
			if (bi == ni && bj == nj) {
				break;
			}
		}
	}
	else {
		if (used[ni][nj] == 0) {
			dfs(ni, nj);
		}
		else {
			curcyc = to[ni][nj];
		}
	}

	if (!num[i][j]) {
		dist[i][j] = dist[ni][nj] + 1;
		to[i][j] = to[ni][nj];
		topt[i][j] = topt[ni][nj];
	}
	used[i][j] = 2;
}

int solve() {
	cin >> n >> m >> g;
	for1(i, n) {
		scanf("\n");
		for1(j, m) {
			scanf("%c", &c[i][j]);
		}
	}

	for1(i, n) {
		for1(j, m) {
			if (!used[i][j]) {
				st.clear();
				dfs(i, j);
			}
		}
	}

	for1(i, n) {
		for1(j, m) {
			int num = to[i][j];
			if (large(i, j)) {
				can[num].pk({i, j});
			}
		}
	}

	for1(i, n) {
		for1(j, m) {
			int c = num[i][j];
			if (c && sq > 0) {
				period[i][j] = len[c] - period[i][j] - 1;
			}
		}
	}

	int answer = 0;
	vector<stans> vans;
	
	for1(c, cycles) {
		int timer = 0, cur = min((int)can[c].size(), len[c]);
		can[c].resize(cur);
		answer += cur;

		if (!g) continue;
		set<int> was;
		forn(i, cur) {
			was.insert(i);
		}

		for (pt p : can[c]) {
			int i = p.i, j = p.j;
			if (num[i][j]) {
				vans.pk({ i, j, 0 });
				int per = period[i][j];
				was.erase(per);
			}
			else {
				int dst = dist[i][j];
				int per = *was.begin();
				was.erase(was.begin());

				int toi = topt[i][j].i, toj = topt[i][j].j;
				int toper = period[toi][toj];

				int dt;
				if (sqr[c] >= 0) {
					dt = toper >= per ? toper - per : len[c] - (per - toper);
				}
				else {
					assert(0);
				}
				int q = 1000;
				int start = len[c] * q + dt - dst - timer;
				vans.pk({ i, j, timer + start });
				timer += start + dst + 1;
			}
		}
	}
	cout << answer << '\n';

	if (g) {
		for (auto a : vans) {
			printf("%d %d %d\n", a.i, a.j, a.t);
		}
	}
	return 0;
}