#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct Dice {
  int face[6];
  // +Z
  int Top() const { return face[0]; }
  int &Top() { return face[0]; }
  // -Z
  int Bottom() const { return face[1]; }
  int &Bottom() { return face[1]; }
  // +X
  int Right() const { return face[2]; }
  int &Right() { return face[2]; }
  // -X
  int Left() const { return face[3]; }
  int &Left() { return face[3]; }
  // +Y
  int Front() const { return face[4]; }
  int &Front() { return face[4]; }
  // -Y
  int Back() const { return face[5]; }
  int &Back() { return face[5]; }

  Dice Rotate(int cnt, int dir) const {
    if (cnt == 0) { return *this; }
    if (cnt < 0) { cnt = cnt % 4 + 4; }
    else { cnt %= 4; }
    Dice ret;
    if (dir == 0) {
      // +X rotate(Y axis rotate)
      ret.face[0] = face[3];
      ret.face[1] = face[2];
      ret.face[2] = face[0];
      ret.face[3] = face[1];
      ret.face[4] = face[4];
      ret.face[5] = face[5];
    } else if (dir == 1) {
      // +Y rotate(X axis rotate)
      ret.face[0] = face[4];
      ret.face[1] = face[5];
      ret.face[2] = face[2];
      ret.face[3] = face[3];
      ret.face[4] = face[1];
      ret.face[5] = face[0];
    } else if (dir == 2) {
      // Z rotate(Z axis rotate)
      ret.face[0] = face[0];
      ret.face[1] = face[1];
      ret.face[2] = face[4];
      ret.face[3] = face[5];
      ret.face[4] = face[3];
      ret.face[5] = face[2];
    } else {
      assert(false);
    }
    return ret.Rotate(cnt - 1, dir);
  }
  vector<Dice> AllRotate() const {
    vector<Dice> ret;
    Dice temp = *this;
    REP(i, 6) {
      REP(j, 4) {
        ret.push_back(temp);
        temp = temp.Rotate(1, 2);
      }
      temp = temp.Rotate(1, i & 1);
    }
    return ret;
  }
  bool operator<(const Dice &rhs) const {
    REP(i, 6) {
      if (face[i] != rhs.face[i]) { return face[i] < rhs.face[i]; }
    }
      return false;
  }
};

int h, w;
char field[100][100];
bool visit[100][100];
const int dx[4] = { 0, 1, 0, -1 };
const int dy[4] = { 1, 0, -1, 0 };

int dfs(int x, int y, Dice &die) {
  if (visit[y][x]) { return 0; }
  visit[y][x] = true;
  int ret = 1;
  die.Bottom() = (int)field[y][x];
  REP(i, 4) {
    int nx = x + dx[i];
    int ny = y + dy[i];
    if (nx < 0 || nx >= w || ny < 0 || ny >= h || field[ny][nx] == '.') { continue; }
    die = die.Rotate(dx[i], 0);
    die = die.Rotate(dy[i], 1);
    ret += dfs(nx, ny, die);
    die = die.Rotate(-dx[i], 0);
    die = die.Rotate(-dy[i], 1);
  }
  return ret;
}

int main() {
  while (scanf("%d %d", &h, &w) > 0) {
    set<Dice> dice;
    MEMSET(field, 0);
    MEMSET(visit, false);
    REP(y, h) {
      scanf("%s", field[y]);
    }
    REP(sy, h) {
      REP(sx, w) {
        if (field[sy][sx] == '.' || visit[sy][sx]) { continue; }
        Dice die;
        REP(i, 6) { die.face[i] = -1; }
        int nret = dfs(sx, sy, die);
        assert(nret == 6);
        REP(i, 6) {
          assert(die.face[i] != -1);
        }
        vector<Dice> rolls = die.AllRotate();
        FORIT(it, rolls) { dice.insert(*it); }
      }
    }
    FORIT(it1, dice) {
      FORIT(it2, dice) {
        if (it1 == it2) { break; }
        Dice big;
        big.Top() = it1->Top();
        big.Right() = it1->Right();
        big.Front() = it1->Front();
        big.Bottom() = it2->Bottom();
        big.Left() = it2->Left();
        big.Back() = it2->Back();
        REP(i, 6) {
          if (big.face[i] == '#') { goto next; }
        }
        REP(i, 6) {
          REP(j, i) {
            if (big.face[i] == big.face[j]) { goto next; }
          }
        }
        REP(i, 8) {
          Dice search;
          search.face[0] = ((i & 1) == 1) ? big.face[0] : (int)'#';
          search.face[1] = ((i & 1) == 0) ? big.face[1] : (int)'#';
          search.face[2] = ((i & 2) == 2) ? big.face[2] : (int)'#';
          search.face[3] = ((i & 2) == 0) ? big.face[3] : (int)'#';
          search.face[4] = ((i & 4) == 4) ? big.face[4] : (int)'#';
          search.face[5] = ((i & 4) == 0) ? big.face[5] : (int)'#';
          if (!dice.count(search)) { goto next; }
        }
        puts("Yes");
        goto end;
next:;
      }
    }
    puts("No");
end:;
  }
}

Measured memory_bytes: 0