#include <bits/stdc++.h>
using namespace std;
inline void read(int &x) {
  x = 0;
  char ch = getchar();
  int f = 1;
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch <= '9' && ch >= '0') {
    x = (x << 3) + (x << 1) + ch - '0';
    ch = getchar();
  }
  x *= f;
}
const int N = 1005;
int n, m;
char ch[N];
bool a[N][N];
vector<vector<int> > generate(vector<int> x, set<int> y) {
  vector<vector<int> > res;
  if (x.size() == 4) {
    res.push_back(x);
    return res;
  } else if (x.size() == 3) {
    for (auto it = y.begin(); it != y.end(); ++it) {
      int s = *it;
      vector<int> temp = x;
      temp.push_back(s), res.push_back(temp);
    }
    return res;
  } else {
    for (auto it1 = y.begin(); it1 != y.end(); ++it1)
      for (auto it2 = y.begin(); it2 != y.end(); ++it2) {
        int s1 = *it1, s2 = *it2;
        vector<int> temp = x;
        temp.push_back(s1), temp.push_back(s2), res.push_back(temp);
      }
    return res;
  }
}
int Size;
bool vis[N][N];
bool judge1(vector<int> x, vector<int> y) {
  int x0 = x[0], x1 = x[1], x2 = x[2], x3 = x[3];
  int y0 = y[0], y1 = y[1], y2 = y[2], y3 = y[3];
  if (x0 > x1 || y0 > y1 || x2 > x3 || y2 > y3) return false;
  if (x1 - x0 < 2 || y1 - y0 < 2 || x3 - x2 < 2 || y3 - y2 < 2) return false;
  int temp = 0;
  bool flag = 1;
  for (int i = (x0); i <= (x1); ++i) {
    if (!a[i][y0]) {
      flag = 0;
      break;
    } else if (!vis[i][y0])
      temp++, vis[i][y0] = 1;
  }
  for (int i = (x0); i <= (x1); ++i) {
    if (!a[i][y1]) {
      flag = 0;
      break;
    } else if (!vis[i][y1])
      temp++, vis[i][y1] = 1;
  }
  for (int i = (x2); i <= (x3); ++i) {
    if (!a[i][y2]) {
      flag = 0;
      break;
    } else if (!vis[i][y2])
      temp++, vis[i][y2] = 1;
  }
  for (int i = (x2); i <= (x3); ++i) {
    if (!a[i][y3]) {
      flag = 0;
      break;
    } else if (!vis[i][y3])
      temp++, vis[i][y3] = 1;
  }
  for (int i = (y0); i <= (y1); ++i) {
    if (!a[x0][i]) {
      flag = 0;
      break;
    } else if (!vis[x0][i])
      temp++, vis[x0][i] = 1;
  }
  for (int i = (y0); i <= (y1); ++i) {
    if (!a[x1][i]) {
      flag = 0;
      break;
    } else if (!vis[x1][i])
      temp++, vis[x1][i] = 1;
  }
  for (int i = (y2); i <= (y3); ++i) {
    if (!a[x2][i]) {
      flag = 0;
      break;
    } else if (!vis[x2][i])
      temp++, vis[x2][i] = 1;
  }
  for (int i = (y2); i <= (y3); ++i) {
    if (!a[x3][i]) {
      flag = 0;
      break;
    } else if (!vis[x3][i])
      temp++, vis[x3][i] = 1;
  }
  for (int i = (x0); i <= (x1); ++i) vis[i][y0] = vis[i][y1] = 0;
  for (int i = (x2); i <= (x3); ++i) vis[i][y2] = vis[i][y3] = 0;
  for (int i = (y0); i <= (y1); ++i) vis[x0][i] = vis[x1][i] = 0;
  for (int i = (y2); i <= (y3); ++i) vis[x2][i] = vis[x3][i] = 0;
  if (!flag) return false;
  if (temp == Size)
    return true;
  else
    return false;
}
void judge(vector<int> x, vector<int> y) {
  sort(x.begin(), x.end());
  while (true) {
    sort(y.begin(), y.end());
    while (true) {
      if (judge1(x, y)) {
        printf("YES\n");
        printf("%d %d %d %d\n", x[0], y[0], x[1], y[1]);
        printf("%d %d %d %d\n", x[2], y[2], x[3], y[3]);
        exit(0);
      } else {
      }
      if (!next_permutation(y.begin(), y.end())) break;
    }
    if (!next_permutation(x.begin(), x.end())) break;
  }
}
int main() {
  scanf("%d %d\n", &n, &m);
  for (int i = (1); i <= (n); ++i) {
    scanf("%s\n", ch + 1);
    for (int j = (1); j <= (m); ++j) a[i][j] = (ch[j] == '#' ? 1 : 0);
  }
  vector<int> tx, ty;
  tx.clear(), ty.clear();
  for (int i = (1); i <= (n); ++i) {
    int cnt = 0;
    bool flag = false;
    for (int j = (1); j <= (m); ++j)
      if (a[i][j]) cnt++;
    if (cnt >= 5) flag = 1;
    for (int j = (1); j <= (m); ++j)
      if (a[i][j] && (i - 1 < 1 || !a[i - 1][j])) flag = 1;
    for (int j = (1); j <= (m); ++j)
      if (a[i][j] && (i + 1 > n || !a[i + 1][j])) flag = 1;
    if (flag) tx.push_back(i);
    Size += cnt;
  }
  for (int i = (1); i <= (m); ++i) {
    int cnt = 0;
    bool flag = false;
    for (int j = (1); j <= (n); ++j)
      if (a[j][i]) cnt++;
    if (cnt >= 5) flag = 1;
    for (int j = (1); j <= (n); ++j)
      if (a[j][i] && (i - 1 < 1 || !a[j][i - 1])) flag = 1;
    for (int j = (1); j <= (n); ++j)
      if (a[j][i] && (i + 1 > m || !a[j][i + 1])) flag = 1;
    if (flag) ty.push_back(i);
  }
  if (tx.size() < 2 || tx.size() > 4 || ty.size() < 2 || ty.size() > 4) {
    printf("NO\n");
    return 0;
  }
  set<int> sx, sy;
  sx.clear(), sy.clear();
  for (auto it = tx.begin(); it != tx.end(); ++it) {
    int y = *it;
    for (int i = (-1); i <= (1); ++i)
      if (tx[0] <= y + i && y + i <= tx[tx.size() - 1]) sx.insert(y + i);
  }
  for (auto it = ty.begin(); it != ty.end(); ++it) {
    int y = *it;
    for (int i = (-1); i <= (1); ++i)
      if (ty[0] <= y + i && y + i <= ty[ty.size() - 1]) sy.insert(y + i);
  }
  vector<vector<int> > X, Y;
  X.clear(), Y.clear();
  X = generate(tx, sx), Y = generate(ty, sy);
  for (auto itx = X.begin(); itx != X.end(); ++itx)
    for (auto ity = Y.begin(); ity != Y.end(); ++ity) {
      vector<int> nowx = *itx, nowy = *ity;
      judge(nowx, nowy);
    }
  printf("NO\n");
  return 0;
}
