#include <bits/stdc++.h>
using namespace std;
const int Nmax = 1005;
char A[Nmax][Nmax];
int used[Nmax][Nmax];
int N, M, cnt = 0;
int currCnt = 0;
bool mark(int x1, int y1, int x2, int y2) {
  for (int i = x1; i <= x2; ++i) {
    if (A[i][y1] == '.' || A[i][y2] == '.') return false;
    if (A[i][y1] == '#') {
      used[i][y1]++;
      if (used[i][y1] == 1) ++currCnt;
    }
    if (A[i][y2] == '#') {
      used[i][y2]++;
      if (used[i][y2] == 1) ++currCnt;
    }
  }
  for (int j = y1 + 1; j < y2; ++j) {
    if (A[x1][j] == '.' || A[x2][j] == '.') return false;
    if (A[x1][j] == '#') {
      used[x1][j]++;
      if (used[x1][j] == 1) ++currCnt;
    }
    if (A[x2][j] == '#') {
      used[x2][j]++;
      if (used[x2][j] == 1) ++currCnt;
    }
  }
  return true;
}
void unmark(int x1, int y1, int x2, int y2) {
  for (int i = x1; i <= x2; ++i) {
    if (A[i][y1] == '.' || A[i][y2] == '.') return;
    if (A[i][y1] == '#') {
      used[i][y1]--;
    }
    if (A[i][y2] == '#') {
      used[i][y2]--;
    }
  }
  for (int j = y1 + 1; j < y2; ++j) {
    if (A[x1][j] == '.' || A[x2][j] == '.') return;
    if (A[x1][j] == '#') {
      used[x1][j]--;
    }
    if (A[x2][j] == '#') {
      used[x2][j]--;
    }
  }
}
bool chooseSecond(const vector<int>& rows, const vector<int>& cols) {
  for (int i = 0; i < int(rows.size()); ++i) {
    for (int j = i + 1; j < int(rows.size()); ++j) {
      int x1 = rows[i], x2 = rows[j];
      if (x2 <= x1 + 1) continue;
      for (int k = 0; k < int(cols.size()); ++k) {
        for (int p = k + 1; p < int(cols.size()); ++p) {
          int y1 = cols[k], y2 = cols[p];
          if (y2 <= y1 + 1) continue;
          int aux = currCnt;
          if (mark(x1, y1, x2, y2) && currCnt == cnt) {
            cout << "YES\n";
            cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\n';
            return true;
          }
          unmark(x1, y1, x2, y2);
          currCnt = aux;
        }
      }
    }
  }
  return false;
}
bool chooseFirst(const vector<int>& rows, const vector<int>& cols) {
  for (int i = 0; i < int(rows.size()); ++i) {
    for (int j = i + 1; j < int(rows.size()); ++j) {
      int x1 = rows[i], x2 = rows[j];
      if (x2 <= x1 + 1) continue;
      for (int k = 0; k < int(cols.size()); ++k) {
        for (int p = k + 1; p < int(cols.size()); ++p) {
          int y1 = cols[k], y2 = cols[p];
          if (y2 <= y1 + 1) continue;
          int aux = currCnt;
          if (mark(x1, y1, x2, y2) && chooseSecond(rows, cols)) {
            cout << x1 << ' ' << y1 << ' ' << x2 << ' ' << y2 << '\n';
            return true;
          }
          unmark(x1, y1, x2, y2);
          currCnt = aux;
        }
      }
    }
  }
  return false;
}
int main() {
  ios::sync_with_stdio(false);
  cin >> N >> M;
  for (int i = 1; i <= N; ++i) {
    cin >> (A[i] + 1);
    for (int j = 1; j <= M; ++j)
      if (A[i][j] == '#') ++cnt;
  }
  vector<int> cols, rows;
  for (int i = 1; i <= N; ++i) {
    bool ok = false;
    for (int j = 1; j + 2 <= M; ++j)
      if (A[i][j] == '#' && A[i][j + 1] == '#' && A[i][j + 2] == '#') ok = true;
    if (ok) rows.push_back(i);
  }
  while (rows.size() > 6U) rows.erase(rows.begin() + rows.size() / 2);
  for (int j = 1; j <= M; ++j) {
    bool ok = false;
    for (int i = 1; i + 2 <= N; ++i)
      if (A[i][j] == '#' && A[i + 1][j] == '#' && A[i + 2][j] == '#') ok = true;
    if (ok) cols.push_back(j);
  }
  while (cols.size() > 6U) cols.erase(cols.begin() + cols.size() / 2);
  if (!chooseFirst(rows, cols)) {
    cout << "NO\n";
  }
}
