#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:64000000")
using namespace std;
const int INF = 1000000000;
const int CardLimit = 54;
const int OneMstCardLimit = 13;
int toNumber(string s) {
  int a = 0;
  int b = 0;
  if (s[1] != '1' && s[1] != '2') {
    if (s[1] == 'C') a = 0;
    if (s[1] == 'D') a = 1;
    if (s[1] == 'H') a = 2;
    if (s[1] == 'S') a = 3;
    if (s[0] >= '0' && s[0] <= '9') b = s[0] - '0' - 2;
    if (s[0] == 'T') b = 8;
    if (s[0] == 'J') b = 9;
    if (s[0] == 'Q') b = 10;
    if (s[0] == 'K') b = 11;
    if (s[0] == 'A') b = 12;
    return a * OneMstCardLimit + b;
  } else {
    if (s[1] == '1') return OneMstCardLimit * 4;
    if (s[1] == '2') return OneMstCardLimit * 4 + 1;
  }
}
string toMst(int numb) {
  if (numb == 4 * OneMstCardLimit) return "J1";
  if (numb == 4 * OneMstCardLimit + 1) return "J2";
  int a = numb / OneMstCardLimit;
  int b = numb % OneMstCardLimit;
  char symb1, symb2;
  if (a == 0) symb1 = 'C';
  if (a == 1) symb1 = 'D';
  if (a == 2) symb1 = 'H';
  if (a == 3) symb1 = 'S';
  if (b >= 0 && b <= 7) symb2 = b + 2 + '0';
  if (b == 8) symb2 = 'T';
  if (b == 9) symb2 = 'J';
  if (b == 10) symb2 = 'Q';
  if (b == 11) symb2 = 'K';
  if (b == 12) symb2 = 'A';
  string ans = "";
  ans += symb2;
  ans += symb1;
  return ans;
}
int n, m;
string T[20][20];
void input() {
  scanf("%d %d", &n, &m);
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) cin >> T[i][j];
}
int joker1i = -1, joker1j = -1, joker1Numb = 1;
int joker2i = -1, joker2j = -1;
vector<string> notOnTable;
bool oneMst(string a, string b) { return a[1] == b[1]; }
bool oneDst(string a, string b) { return a[0] == b[0]; }
bool itsJoker(string a) { return a[1] == '1' || a[1] == '2'; }
void formGoodData() {
  bool B[54] = {};
  for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++) {
      B[toNumber(T[i][j])] = 1;
      if (itsJoker(T[i][j]))
        if (T[i][j][1] == '1')
          joker1i = i, joker1j = j;
        else
          joker2i = i, joker2j = j;
    }
  if (joker1i == -1 && joker2i != -1)
    swap(joker1i, joker2i), swap(joker1j, joker2j), joker1Numb = 2;
  for (int i = 0; i < 52; i++)
    if (!B[i]) notOnTable.push_back(toMst(i));
}
bool checkOnOneMst(int n1, int m1) {
  if (n - n1 < 3 || m - m1 < 3) return false;
  for (int i = n1; i < n1 + 3; i++)
    for (int j = m1; j < m1 + 3; j++) {
      if (!oneMst(T[i][j], T[n1][m1])) return false;
    }
  return true;
}
bool checkOnDifDst(int n1, int m1) {
  if (n - n1 < 3 || m - m1 < 3) return false;
  for (int i1 = n1; i1 < n1 + 3; i1++)
    for (int j1 = m1; j1 < m1 + 3; j1++)
      for (int i2 = n1; i2 < n1 + 3; i2++)
        for (int j2 = m1; j2 < m1 + 3; j2++) {
          if (i1 == i2 && j1 == j2) continue;
          if (oneDst(T[i1][j1], T[i2][j2])) return false;
        }
  return true;
}
bool answerExist = false;
int oneMstN1 = -1, oneMstM1 = -1, difDstN1 = -1, difDstM1 = -1;
inline int mabs(int a) { return a < 0 ? -a : a; }
bool globalCheck() {
  for (int i1 = 0; i1 <= n - 3; i1++)
    for (int j1 = 0; j1 <= m - 3; j1++)
      for (int i2 = 0; i2 <= n - 3; i2++)
        for (int j2 = 0; j2 <= m - 3; j2++) {
          if (i2 == 3 && j2 == 0 && i1 == 0 && j1 == 0) int STOP = 1;
          if (mabs(i2 - i1) < 3 && mabs(j2 - j1) < 3) continue;
          if ((checkOnOneMst(i1, j1) || checkOnDifDst(i1, j1)) &&
              (checkOnDifDst(i2, j2) || checkOnOneMst(i2, j2))) {
            oneMstN1 = i1;
            oneMstM1 = j1;
            difDstN1 = i2;
            difDstM1 = j2;
            return true;
          }
        }
  return false;
}
void solve() {
  if (joker1i == -1)
    if (globalCheck()) {
      cout << "Solution exists." << endl;
      cout << "There are no jokers." << endl;
      if (make_pair(oneMstN1, oneMstM1) > make_pair(difDstN1, difDstM1))
        swap(oneMstN1, difDstN1), swap(oneMstM1, difDstM1);
      cout << "Put the first square to (" << oneMstN1 + 1 << ", "
           << oneMstM1 + 1 << ")." << endl;
      cout << "Put the second square to (" << difDstN1 + 1 << ", "
           << difDstM1 + 1 << ")." << endl;
    } else {
      cout << "No solution." << endl;
    }
  if (joker1i != -1 && joker2i == -1) {
    for (int t = 0; t < notOnTable.size(); t++) {
      T[joker1i][joker1j] = notOnTable[t];
      if (globalCheck()) {
        cout << "Solution exists." << endl;
        cout << "Replace J" << joker1Numb << " with " << notOnTable[t] << "."
             << endl;
        if (make_pair(oneMstN1, oneMstM1) > make_pair(difDstN1, difDstM1))
          swap(oneMstN1, difDstN1), swap(oneMstM1, difDstM1);
        cout << "Put the first square to (" << oneMstN1 + 1 << ", "
             << oneMstM1 + 1 << ")." << endl;
        cout << "Put the second square to (" << difDstN1 + 1 << ", "
             << difDstM1 + 1 << ")." << endl;
        return;
      }
    }
    cout << "No solution." << endl;
  }
  if (joker1i != -1 && joker2i != -1) {
    for (int t1 = 0; t1 < notOnTable.size(); t1++)
      for (int t2 = 0; t2 < notOnTable.size(); t2++) {
        if (t1 == t2) continue;
        T[joker1i][joker1j] = notOnTable[t1];
        T[joker2i][joker2j] = notOnTable[t2];
        if (globalCheck()) {
          cout << "Solution exists." << endl;
          cout << "Replace J1 with " << notOnTable[t1] << " and J2 with "
               << notOnTable[t2] << "." << endl;
          if (make_pair(oneMstN1, oneMstM1) > make_pair(difDstN1, difDstM1))
            swap(oneMstN1, difDstN1), swap(oneMstM1, difDstM1);
          cout << "Put the first square to (" << oneMstN1 + 1 << ", "
               << oneMstM1 + 1 << ")." << endl;
          cout << "Put the second square to (" << difDstN1 + 1 << ", "
               << difDstM1 + 1 << ")." << endl;
          return;
        }
      }
    cout << "No solution." << endl;
  }
}
int main() {
  input();
  formGoodData();
  solve();
  return 0;
}
