1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#if defined(EMBE_DEBUG) && !defined(NDEBUG)
#include "embe-debug.hpp"
#else
#define LOG_INDENT(...) do {} while (false)
#define LOG(...) do {} while (false)
#define DUMP(...) do {} while (false)
#endif

#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <ranges>
#include <string>
#include <tuple>
#include <vector>
using namespace std;

namespace {

vector<tuple<char, int, char>> solve(vector<string> const& target)
{
  vector<tuple<char, int, char>> res;

  int n = target.size();
  int m = target[0].size();

  vector<int> rows;
  ranges::copy(views::iota(0, n), back_inserter(rows));

  vector<int> cols;
  ranges::copy(views::iota(0, m), back_inserter(cols));

  auto row_colors = vector(26, vector(n, 0));
  auto col_colors = vector(26, vector(m, 0));

  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      int c = target[i][j] - 'A';
      ++row_colors[c][i];
      ++col_colors[c][j];
    }
  }

  vector<int> new_rows;
  new_rows.reserve(n);
  vector<int> new_cols;
  new_cols.reserve(m);
  while (!rows.empty() && !cols.empty()) {
    new_rows.clear();
    for (int i: rows) {
      bool found = false;
      for (int c = 0; c < 26; ++c) {
        if (row_colors[c][i] == int(cols.size())) {
          res.emplace_back('R', i + 1, 'A' + c);
          for (int j: cols) {
            --col_colors[target[i][j] - 'A'][j];
          }
          found = true;
          break;
        }
      }
      if (!found) {
        new_rows.push_back(i);
      }
    }
    swap(new_rows, rows);

    if (rows.empty()) break;

    new_cols.clear();
    for (int j: cols) {
      bool found = false;
      for (int c = 0; c < 26; ++c) {
        if (col_colors[c][j] == int(rows.size())) {
          res.emplace_back('K', j + 1, 'A' + c);
          for (int i: rows) {
            --row_colors[target[i][j] - 'A'][i];
          }
          found = true;
          break;
        }
      }
      if (!found) {
        new_cols.push_back(j);
      }
    }
    swap(new_cols, cols);
  }

  ranges::reverse(res);
  return res;
}

}

int main()
{
  iostream::sync_with_stdio(false);
  cin.tie(nullptr);

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

  vector<string> target(n);
  for (auto& s: target) {
    cin >> s;
    assert(int(s.size()) == m);
  }

  auto res = solve(target);
  cout << res.size() << '\n';
  for (auto [op, x, c]: res) {
    cout << op << ' ' << x << ' ' << c << '\n';
  }

  return 0;
}