#include <bits/stdc++.h>
using namespace std;
inline void FAST_IO() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
}
template <class F, class S>
ostream& operator<<(ostream& os, pair<F, S>& p) {
  os << "(" << p.first << "," << p.second << ")";
  return os;
}
template <class T, class S>
ostream& operator<<(ostream& os, map<T, S>& v) {
  os << "{";
  for (auto& i : v) cout << "{" << i.first << "," << i.second << "}";
  os << "}";
  return os;
}
template <class T>
ostream& operator<<(ostream& os, set<T>& v) {
  os << "{";
  for (auto& i : v) cout << i << ",";
  os << "}";
  return os;
}
template <class T>
ostream& operator<<(ostream& os, vector<T>& v) {
  os << "[";
  if (v.size()) os << v[0];
  for (int i = 1; i < v.size(); ++i) os << "," << v[i];
  os << "]";
  return os;
}
int main() {
  char hanks[13]{'2', '3', '4', '5', '6', '7', '8',
                 '9', 'T', 'J', 'Q', 'K', 'A'};
  char suits[4]{'C', 'D', 'H', 'S'};
  int n, m;
  cin >> n >> m;
  vector<vector<string>> board(n, vector<string>(m));
  set<string> used;
  vector<pair<int, int>> pos;
  vector<string> joker;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      cin >> board[i][j];
      used.insert(board[i][j]);
      if (board[i][j] == "J1" || board[i][j] == "J2") {
        pos.push_back({i, j});
        joker.push_back(board[i][j]);
      }
    }
  }
  if (pos.size() == 2) {
    if (joker[0] == "J2") {
      swap(joker[0], joker[1]);
      swap(pos[0], pos[1]);
    }
  }
  set<string> free;
  for (auto h : hanks) {
    for (auto s : suits) {
      string card{h, s};
      if (!used.count(card)) {
        free.insert(card);
      }
    }
  }
  function<void(set<string>, int)> iterate = [&](set<string> term, int it) {
    if (it != pos.size()) {
      int i = pos[it].first;
      int j = pos[it].second;
      for (auto f : free) {
        if (!term.count(f)) {
          board[i][j] = f;
          term.insert(f);
          iterate(term, it + 1);
          term.erase(f);
        }
      }
    } else {
      vector<pair<int, int>> resp;
      for (int i = 0; i <= n - 3; ++i) {
        for (int j = 0; j <= m - 3; ++j) {
          set<char> hank;
          set<char> suit;
          for (int a = 0; a < 3; ++a) {
            for (int b = 0; b < 3; ++b) {
              int r = i + a;
              int c = j + b;
              hank.insert(board[r][c][0]);
              suit.insert(board[r][c][1]);
            }
          }
          if (hank.size() == 9 || suit.size() == 9) resp.push_back({i, j});
        }
      }
      vector<pair<int, int>> resp_filtered;
      for (auto p1 : resp) {
        int matches = 0;
        for (auto p2 : resp) {
          if (p1 == p2) continue;
          if (abs(p1.first - p2.first) >= 3 ||
              abs(p1.second - p2.second) >= 3) {
            resp_filtered.push_back(p1);
            resp_filtered.push_back(p2);
            break;
          }
        }
        if (resp_filtered.size() >= 2) break;
      }
      if (resp_filtered.size() == 2) {
        printf("Solution exists.\n");
        if (pos.size() == 0) {
          printf("There are no jokers.\n");
        } else if (pos.size() == 1) {
          printf("Replace %s with %s.\n", joker[0].c_str(),
                 board[pos[0].first][pos[0].second].c_str());
        } else {
          printf("Replace J1 with %s and J2 with %s.\n",
                 board[pos[0].first][pos[0].second].c_str(),
                 board[pos[1].first][pos[1].second].c_str());
        }
        printf("Put the first square to (%d, %d).\n",
               resp_filtered[0].first + 1, resp_filtered[0].second + 1);
        printf("Put the second square to (%d, %d).\n",
               resp_filtered[1].first + 1, resp_filtered[1].second + 1);
        exit(0);
      }
    }
  };
  iterate({}, 0);
  printf("No solution.\n");
  return 0;
}
