#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <ciso646>
#include <cmath>
#include <cassert>
#include <cstring>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <stack>
#include <deque>
#include <list>
#include <initializer_list>
#include <algorithm>
#include <string>
using namespace std;
typedef long long ll;
typedef long double ld;

time_t _timer;
void _pre()
{
	_timer = clock();
	ios_base::sync_with_stdio(false);
	cin.tie(nullptr);
#ifdef ANDREIKKAA
	assert(freopen("input.txt", "r", stdin) != nullptr);
#else
	assert(freopen("robots.in", "r", stdin) != nullptr);
	assert(freopen("robots.out", "w", stdout) != nullptr);
#endif
}

void _post()
{
#ifdef ANDREIKKAA
	cout << "\n\n\nTime: " << (clock() - _timer) / (ld)CLOCKS_PER_SEC << endl;
	while (228);
#endif
}

const int MAX_S = 50;
int dx[256];
int dy[256];
int num[MAX_S][MAX_S];
char a[MAX_S][MAX_S];
bool is[MAX_S][MAX_S];
bool used[MAX_S][MAX_S];
bool u_cyc[MAX_S][MAX_S];
bool bad[MAX_S * MAX_S];
int dsu[MAX_S * MAX_S];
int dsu_cnt;
int a_x[MAX_S * MAX_S];
int a_y[MAX_S * MAX_S];
int a_t[MAX_S * MAX_S];
int a_ptr = 0;

int dsu_get(int x)
{
	if (not bad[x])
	{
		bad[x] = true;
		--dsu_cnt;
		return x;
	}
	return dsu[x] = dsu_get(dsu[x]);
}

inline void go(int &x, int &y)
{
	int nx = x + dx[a[x][y]];
	y += dy[a[x][y]];
	x = nx;
}

inline void solve_cycle(int x, int y)
{
	static int qx[MAX_S * MAX_S];
	static int qy[MAX_S * MAX_S];
	static int qd[MAX_S * MAX_S];
	static int ptr[MAX_S * MAX_S];

	while (not u_cyc[x][y])
	{
		u_cyc[x][y] = true;
		go(x, y);
	}

	int cx = x, cy = y;
	int nu = 1;
	dsu_cnt = 0;
	do
	{
		used[cx][cy] = true;
		dsu[nu] = nu - 1;
		bad[nu] = false;
		if (is[cx][cy])
		{
			is[cx][cy] = false;
			dsu_get(nu);
			a_x[a_ptr] = cx;
			a_y[a_ptr] = cy;
			a_t[a_ptr] = 0;
			++a_ptr;
		}
		num[cx][cy] = nu;
		++nu;
		go(cx, cy);
	} while (cx != x or cy != y);
	--nu;
	dsu[1] = nu;
	dsu_cnt += nu;

	do
	{
		int ql = 0, qr = 0;
		qx[qr] = cx;
		qy[qr] = cy;
		qd[qr] = 0;
		++qr;
		while (ql != qr)
		{
			int xx = qx[ql];
			int yy = qy[ql];
			int dd = qd[ql];
			++ql;
			used[xx][yy] = true;

			if (is[xx][yy] and dsu_cnt > 0)
			{
				is[xx][yy] = false;
				int tim = ((num[cx][cy] - dd) % nu + nu);
				if (tim > nu)
					tim -= nu;
				int pos = dsu_get(tim);
				//ON (TIM - POS + NU) % NU
				a_x[a_ptr] = xx;
				a_y[a_ptr] = yy;
				a_t[a_ptr] = (tim - pos + nu) % nu;
				++a_ptr;
			}

			for (char i : {'n', 's', 'e', 'w'})
			{
				int tx = xx + dx[i];
				int ty = yy + dy[i];
				if (num[tx][ty] != 0)
					continue;
				go(tx, ty);
				if (tx == xx and ty == yy)
				{
					qx[qr] = xx + dx[i];
					qy[qr] = yy + dy[i];
					qd[qr] = dd + 1;
					++qr;
				}
			}
		}

		go(cx, cy);
	} while (cx != x or cy != y);
}

void _solve()
{
	dx['n'] = -1;
	dx['s'] = 1;
	dy['e'] = 1;
	dy['w'] = -1;

	int n, m, g;
	cin >> n >> m >> g;

	for (int i = 1; i <= n; ++i)
	{
		cin >> (a[i] + 1);
		for (int j = 1; j <= m; ++j)
		{
			if (a[i][j] < 'a')
			{
				is[i][j] = true;
				a[i][j] += 'a' - 'A';
			}
		}
	}

	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= m; ++j)
		{
			if (not used[i][j])
			{
				solve_cycle(i, j);
			}
		}
	}

	cout << a_ptr << endl;
	for (int i = 0; i < a_ptr; ++i)
		cout << a_x[i] << " " << a_y[i] << " " << a_t[i] << "\n";
}

int main()
{
	_pre();
	_solve();
	_post();
}