Mary Thomas has a number of sheets of squared paper. Some of squares are painted either in black or some colorful color (such as red and blue) on the front side. Cutting off the unpainted part, she will have eight opened-up unit cubes. A unit cube here refers to a cube of which each face consists of one square.

She is going to build those eight unit cubes with the front side exposed and then a bicube with them. A bicube is a cube of the size 2 × 2 × 2, consisting of eight unit cubes, that satisfies the following conditions:

* faces of the unit cubes that comes to the inside of the bicube are all black;
* each face of the bicube has a uniform colorful color; and
* the faces of the bicube have colors all different.



Your task is to write a program that reads the specification of a sheet of squared paper and decides whether a bicube can be built with the eight unit cubes resulting from it.



Input

The input contains the specification of a sheet. The first line contains two integers H and W, which denote the height and width of the sheet (3 ≤ H, W ≤ 50). Then H lines follow, each consisting of W characters. These lines show the squares on the front side of the sheet. A character represents the color of a grid: alphabets and digits ('A' to 'Z', 'a' to 'z', '0' to '9') for colorful squares, a hash ('#') for a black square, and a dot ('.') for an unpainted square. Each alphabet or digit denotes a unique color: squares have the same color if and only if they are represented by the same character.

Each component of connected squares forms one opened-up cube. Squares are regarded as connected when they have a common edge; those just with a common vertex are not.

Output

Print "Yes" if a bicube can be built with the given sheet; "No" otherwise.

Examples

Input

3 40
.a....a....a....a....f....f....f....f...
#bc#.#cd#.#de#.#eb#.#cb#.#dc#.#ed#.#be#.
.#....#....#....#....#....#....#....#...


Output

Yes


Input

3 40
.a....a....a....a....f....f....f....f...
bc#.#cd#.#de#.#eb#.#cb#.#dc#.#ed#.#be#.
.#....#....#....#....#....#....#....#...


Output

Yes


Input

5 35
.a....a....a....a....f....f....f...
bc#.#cd#.#de#.#eb#.#cb#.#dc#.#ed#.
.#..f.#....#....#....#....#....#...
..e##..............................
.b#................................


Output

Yes


Input

3 40
.a....a....a....a....f....f....f....f...
bc#.#cd#.#de#.#eb#.#cb#.#dc#.#ed#.#eb#.
.#....#....#....#....#....#....#....#...


Output

No
#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<b?(a=b,1):0)
#define chmin(a,b) (a>b?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

const int dy[4] = {-1,0,1,0};
const int dx[4] = {0,1,0,-1};

template <class T>
struct dice {
  T t,b,n,s,e,w;              // top bottom north south east west
  int x, y;
  dice() {t=' ';}
  dice(int y, int x) : y(y),x(x) {
    t=0,b=1,n=2,s=3,e=4,w=5;
  }
  dice(T t, T b, T n, T s, T e, T w) : t(t),b(b),n(n),s(s),e(e),w(w) {}
  void roll(T &a, T &b, T &c, T &d) { swap(a,b); swap(b,c); swap(c,d); }
  void roll_x() { roll(t, n, b, s); }
  void roll_y() { roll(t, w, b, e); }
  void roll_z() { roll(s, e, n, w); }
  vector<dice> all_rolls() {
    vector<dice> ret;
    for (int k=0; k<6; (k&1?roll_y():roll_x()),++k)
      for (int i=0; i<4; roll_z(), ++i)
        ret.push_back(*this);
    return ret;
  }
  void roll(int d) {
    if (d == 0) roll(t, s, b, n);
    else if (d == 1) roll(t, w, b, e);
    else if (d == 2) roll(t, n, b, s);
    else roll(t, e, b, w);
    x+=dx[d];
    y+=dy[d];
  }
  void toTable(T *res) {
    res[0]=t;res[1]=b;res[2]=n;
    res[3]=s;res[4]=e;res[5]=w;
  }
};

typedef dice<char> Dice;

Dice di[8][24];
Dice cube[2][2][2];

int posx[8] = {0,1,0,1,0,1,0,1};
int posy[8] = {0,0,1,1,0,0,1,1};
int posz[8] = {0,0,0,0,1,1,1,1};

const int dx3[6] = {0,0,-1,1,0,0};
const int dy3[6] = {0,0,0,0,1,-1};
const int dz3[6] = {1,-1,0,0,0,0};

bool check(int x, int y, int z, vector<char> &v) {
  char table[6];
  cube[x][y][z].toTable(table);

  // if (x==1) {
  //   cout << " ";
  //   REP(i,6) cout << table[i] << ","; cout << endl;
  // }

  REP(i,6) {
    int xx=x+dx3[i];
    int yy=y+dy3[i];
    int zz=z+dz3[i];
    int p = -1;
    if (xx<0) p=0;
    else if (xx>=2) p=1;
    else if (yy<0) p=2;
    else if (yy>=2) p=3;
    else if (zz<0) p=4;
    else if (zz>=2) p=5;

    // if (x==1) {
    //   if (p>=0) cout << v[p] << " ";
    //   cout << p << " " << table[i] << endl;
    // }

    if (p==-1 ^ table[i]=='#') return 0;                 // 内側は必ず黒．外側は黒以外
    if (p!=-1 && v[p]!='.'&& v[p]!=table[i]) return 0; // 外側の色
    if (p>=0) v[p] = table[i];
  }
  return 1;
}

bool solve(int cnt, int S, vector<char> v) {
  // cout << cnt << endl;
  // FOR(it, v) cout << *it; cout << endl;
  if (cnt == 8) {
    set<char> st;
    FOR(it, v) st.insert(*it);
    return st.size() == 6;
  }

  REP(i,8) {
    if (S>>i&1) continue;
    REP(j,24) {
      int x = posx[cnt];
      int y = posy[cnt];
      int z = posz[cnt];
      cube[x][y][z] = di[i][j];
      vector<char> nxt(v);
      if (!check(x,y,z,nxt)) continue;
      // cout << i << " " << j << endl;
      if (solve(cnt+1, S|1<<i, nxt)) return 1;
    }
  }
  return 0;
}


bool visited[50][50];
char c[50][50];

int main() {
  int h,w;
  cin >> h >> w;
  REP(i,h)REP(j,w)cin>>c[i][j];
  char array[8][6];
  int num = 0;
  REP(i,h)REP(j,w)if(c[i][j]!='.'&&!visited[i][j]) {
    queue<Dice> Q;
    Q.push(Dice(i,j));
    visited[i][j] = 1;
    while(!Q.empty()) {
      Dice now = Q.front(); Q.pop();
      array[num][now.b] = c[now.y][now.x];
      REP(k,4) {
        int y=now.y+dy[k];
        int x=now.x+dx[k];
        if (!valid(y,x,h,w)) continue;
        if (c[y][x] == '.') continue;
        if (!visited[y][x]) {
          visited[y][x] = 1;
          Dice nxt = now;
          nxt.roll(k);
          Q.push(nxt);
        }
      }
    }
    num++;
  }
  assert(num == 8);
  REP(i,num) {
    // REP(j,6) cout << array[i][j] << " "; cout << endl;
    char *a = array[i];
    Dice tmp(a[0],a[1],a[2],a[3],a[4],a[5]);
    vector<Dice> V = tmp.all_rolls();
    REP(j,V.size()) {
      di[i][j] = V[j];
    }
  }
  vector<char> v(6,'.');
  cout << (solve(0,0,v)?"Yes":"No") << endl;
}