#pragma comment(linker, "/Stack:512000000")
#define	_CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <cctype>
#include <unordered_set>
#include <unordered_map>

using namespace std;

typedef long long LL;
typedef double dbl;

#define all(x) (x).begin(), (x).end()

const int INF = (int)1e9;
const int MOD = (int)1e9 + 7;
const dbl EPS = 1e-9;


namespace g0 {

  vector<int> g;
  vector<char> has;
  vector<int> p;
  vector<char> used;
  vector<int> cycleid;
  int id;
  vector<int> cycles;
  vector<int> robots;

  int dfs(int v) {
    cycleid[v] = id;
    used[v] = 1;
    p.push_back(v);

    if (used[g[v]] == 1) {
      int len = 1;
      while (p.size() && p.back() != g[v]) {
        len++;
        p.pop_back();
      }
      used[v] = 2;
      cycles[cycleid[v]] = len;
      return len;
    }
    else if (!used[g[v]]) {
      int ans = dfs(g[v]);
      used[v] = 2;
      if (p.size() && p.back() == v)
        p.pop_back();
      return ans;
    }
    else {
      int tid = cycleid[g[v]];
      for (auto t : p) {
        cycleid[t] = tid;
      }
    }
    used[v] = 2;
    if (p.size() && p.back() == v)
      p.pop_back();
    return 0;
  }

  void solve(int n, int m) {
    g.resize(n * m);
    used.resize(n * m);
    p.reserve(n * m);
    has.resize(n * m);
    cycleid.resize(n * m);
    cycles.push_back(0);
    for (int i = 0; i < n; ++i) {
      string s;
      cin >> s;
      for (int j = 0; j < m; ++j) {
        switch (toupper(s[j])) {
        case 'N':
          g[i * m + j] = (i - 1) * m + j;
          break;
        case 'S':
          g[i * m + j] = (i + 1) * m + j;
          break;
        case 'E':
          g[i * m + j] = i * m + j + 1;
          break;
        case 'W':
          g[i * m + j] = i * m + j - 1;
          break;
        }
        if (isupper(s[j])) {
          has[i * m + j] = 1;
        }
      }
    }

    id = 0;
    int ans = 0;
    for (int i = 0; i < n * m; ++i) {
      if (!used[i]) {
        id++;
        cycles.push_back(0);
        dfs(i);
      }
    }

    robots.resize(cycles.size());

    for (int i = 0; i < n * m; ++i) {
      robots[cycleid[i]] += has[i];
    }

    for (int i = 0; i < cycles.size(); ++i) {
      ans += min(cycles[i], robots[i]);
    }

    cout << ans << endl;
  }
}

namespace g1 {
  vector<int> g;
  vector<char> hasrobot;
  vector<int> p;
  vector<char> used;
  vector<int> cycleid;
  int id;
  vector<int> cycles;
  vector<int> robots;
  vector<int> cyclesfilled;
  int timer = 1;
  vector<int> activationtime;
  vector<vector<pair<int, int>>> tocycle;
  vector<vector<int>> oncycle;
  vector<int> tocycleptr;
  vector<int> tocyclelen;
  vector<int> tocycleid;
  vector<vector<int>> cycleused;

  int dfs(int v) {
    cycleid[v] = id;
    used[v] = 1;
    p.push_back(v);

    if (used[g[v]] == 1) {
      int len = 1;
      while (p.size() && p.back() != g[v]) {
        tocycle[id].push_back({ p.back(), 0 });
        tocyclelen[p.back()] = 0;
        oncycle[id].push_back(p.back());
        tocycleid[p.back()] = p.back();
        len++;
        p.pop_back();
      }

      tocycle[id].push_back({ g[v], 0 });
      tocyclelen[g[v]] = 0;
      oncycle[id].push_back(g[v]);
      tocycleid[g[v]] = g[v];

      used[v] = 2;
      cycles[cycleid[v]] = len;
      p.pop_back();
      return 1;
    }
    else if (!used[g[v]]) {
      int ans = dfs(g[v]);
      used[v] = 2;
      if (p.size() && p.back() == v) {
        p.pop_back();
        tocycle[cycleid[v]].push_back({ v, tocyclelen[g[v]] + 1 });
        tocycleid[v] = tocyclelen[g[v]] == 0 ? g[v] : tocycleid[g[v]];
        tocyclelen[v] = tocyclelen[g[v]] + 1;
      }
      return 0;
    }
    else {
      int tid = cycleid[g[v]];
      for (auto t : p) {
        cycleid[t] = tid;
      }
    }
    used[v] = 2;
    if (p.size() && p.back() == v) {
      p.pop_back();
      tocycle[cycleid[v]].push_back({ v, tocyclelen[g[v]] + 1 });
      tocycleid[v] = tocyclelen[g[v]] == 0 ? g[v] : tocycleid[g[v]];
      tocyclelen[v] = tocyclelen[g[v]] + 1;
    }
    return 0;
  }

  void solve(int n, int m) {
    g.resize(n * m);
    used.resize(n * m);
    p.reserve(n * m);
    hasrobot.resize(n * m);
    tocycleid.resize(n * m);
    cycleid.resize(n * m);
    cycles.push_back(0);
    cyclesfilled.push_back(0);
    tocycleptr.push_back(0);
    oncycle.push_back(vector<int>());
    cycleused.push_back(vector<int>());
    tocycle.push_back(vector < pair<int, int>>());
    activationtime.resize(n * m);
    tocyclelen.resize(n * m);
    for (int i = 0; i < n; ++i) {
      string s;
      cin >> s;
      for (int j = 0; j < m; ++j) {
        switch (toupper(s[j])) {
        case 'N':
          g[i * m + j] = (i - 1) * m + j;
          break;
        case 'S':
          g[i * m + j] = (i + 1) * m + j;
          break;
        case 'E':
          g[i * m + j] = i * m + j + 1;
          break;
        case 'W':
          g[i * m + j] = i * m + j - 1;
          break;
        }
        if (isupper(s[j])) {
          hasrobot[i * m + j] = 1;
        }
      }
    }

    id = 0;
    int ans = 0;
    for (int i = 0; i < n * m; ++i) {
      if (!used[i]) {
        id++;
        cycles.push_back(0);
        cyclesfilled.push_back(0);
        tocycleptr.push_back(0);
        oncycle.push_back(vector<int>());
        cycleused.push_back(vector<int>());
        tocycle.push_back(vector < pair<int, int>>());
        dfs(i);
      }
    }

    robots.resize(cycles.size());

    for (int i = 0; i < n * m; ++i) {
      robots[cycleid[i]] += hasrobot[i];
    }

    for (int i = 0; i < cycles.size(); ++i) {
      ans += min(cycles[i], robots[i]);
      unordered_map<int, int> conv;
      reverse(all(oncycle[i]));
      for (int j = 0; j < oncycle[i].size(); ++j)
        conv[oncycle[i][j]] = j;
      cycleused[i].resize(oncycle[i].size());
      random_shuffle(all(tocycle[i]));
      while (cyclesfilled[i] != min(robots[i], cycles[i])) {
        int j = tocycleptr[i]++;
        int to = tocycle[i][j].first, len = tocycle[i][j].second, tid = tocycleid[tocycle[i][j].first];
        if (!hasrobot[to]) continue;

        int toid = oncycle[i][(conv[tid] + len + timer + 1ll * oncycle[i].size() * INF) % oncycle[i].size()];

        while (cycleused[i][conv[toid]]) {
          timer++;
          toid = oncycle[i][(conv[tid] + len + timer + 1ll * oncycle[i].size() * INF) % oncycle[i].size()];
        }

        cycleused[i][conv[toid]] = 1;

        activationtime[to] = timer;
        ++cyclesfilled[i];

      }
    }

    cout << ans << '\n';

    for (int i = 0; i < n * m; ++i) {
      if (!activationtime[i]) continue;
      cout << i / m + 1 << ' ' << i % m + 1 << ' ' << activationtime[i] << '\n';
    }

    
  }
}

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#elif 1
#define PROB "robots"
	freopen(PROB".in", "r", stdin);
	freopen(PROB".out", "w", stdout);
#endif
	cin.tie(0);
	cin.sync_with_stdio(0);

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

  if (!g) {
    using namespace g0;
    solve(n, m);
  }
  else {
    using namespace g1;
    solve(n, m);
  }

	return 0;
}