#include <bits/stdc++.h>
using namespace std;
const int MAXS = 100010;
const int MAXN = 310;
char buf[MAXS];
int n, m;
deque<int> start[MAXN][MAXN];
deque<int> stop[MAXN][MAXN];
struct Move {
  int x1, y1;
  int x2, y2;
  Move(int _x1, int _y1, int _x2, int _y2) {
    x1 = _x1;
    y1 = _y1;
    x2 = _x2;
    y2 = _y2;
  }
};
vector<Move> CanonES(deque<int> in[MAXN][MAXN]) {
  vector<Move> moves;
  vector<int> tr(m, 0);
  vector<int> br(m, 0);
  for (int j = 0; j < m; ++j) {
    tr[j] = ((int)(in[0][j]).size());
    br[j] = ((int)(in[n - 1][j]).size());
  }
  for (int i = 1; i < n - 1; ++i) {
    for (int j = 0; j < m; ++j) {
      while (!in[i][j].empty()) {
        if (in[i][j].back() == 0) {
          moves.push_back(Move(i, j, 0, j));
          in[0][j].push_front(in[i][j].back());
          in[i][j].pop_back();
        } else {
          moves.push_back(Move(i, j, n - 1, j));
          in[n - 1][j].push_front(in[i][j].back());
          in[i][j].pop_back();
        }
      }
    }
  }
  for (int j = 0; j < m; ++j) {
    while (tr[j] > 0) {
      --tr[j];
      if (in[0][j].back() == 0) {
        int to = 0;
        if (j == 0) to = 1;
        moves.push_back(Move(0, j, 0, to));
        in[0][to].push_front(in[0][j].back());
        in[0][j].pop_back();
      } else {
        moves.push_back(Move(0, j, n - 1, j));
        in[n - 1][j].push_front(in[0][j].back());
        in[0][j].pop_back();
      }
    }
  }
  for (int j = 0; j < m; ++j) {
    while (br[j] > 0) {
      --br[j];
      if (in[n - 1][j].back() == 1) {
        int to = 0;
        if (j == 0) to = 1;
        moves.push_back(Move(n - 1, j, n - 1, to));
        in[n - 1][to].push_front(in[n - 1][j].back());
        in[n - 1][j].pop_back();
      } else {
        moves.push_back(Move(n - 1, j, 0, j));
        in[0][j].push_front(in[n - 1][j].back());
        in[n - 1][j].pop_back();
      }
    }
  }
  for (int j = 1; j < m; ++j) {
    while (!in[0][j].empty()) {
      moves.push_back(Move(0, j, 0, 0));
      in[0][j].pop_back();
    }
    while (!in[n - 1][j].empty()) {
      moves.push_back(Move(n - 1, j, n - 1, 0));
      in[n - 1][j].pop_back();
    }
  }
  return moves;
}
vector<Move> CanonSE(deque<int> in[MAXN][MAXN]) {
  vector<Move> moves;
  vector<int> tr(m, 0);
  vector<int> br(m, 0);
  for (int j = 0; j < m; ++j) {
    tr[j] = ((int)(in[0][j]).size());
    br[j] = ((int)(in[n - 1][j]).size());
  }
  for (int i = 1; i < n - 1; ++i) {
    for (int j = 0; j < m; ++j) {
      while (!in[i][j].empty()) {
        if (in[i][j].front() == 0) {
          moves.push_back(Move(i, j, 0, j));
          in[0][j].push_back(in[i][j].front());
          in[i][j].pop_front();
        } else {
          moves.push_back(Move(i, j, n - 1, j));
          in[n - 1][j].push_back(in[i][j].front());
          in[i][j].pop_front();
        }
      }
    }
  }
  for (int j = 0; j < m; ++j) {
    while (tr[j] > 0) {
      --tr[j];
      if (in[0][j].front() == 0) {
        int to = 0;
        if (j == 0) to = 1;
        moves.push_back(Move(0, j, 0, to));
        in[0][to].push_back(in[0][j].front());
        in[0][j].pop_front();
      } else {
        moves.push_back(Move(0, j, n - 1, j));
        in[n - 1][j].push_back(in[0][j].front());
        in[0][j].pop_front();
      }
    }
  }
  for (int j = 0; j < m; ++j) {
    while (br[j] > 0) {
      --br[j];
      if (in[n - 1][j].front() == 1) {
        int to = 0;
        if (j == 0) to = 1;
        moves.push_back(Move(n - 1, j, n - 1, to));
        in[n - 1][to].push_back(in[n - 1][j].front());
        in[n - 1][j].pop_front();
      } else {
        moves.push_back(Move(n - 1, j, 0, j));
        in[0][j].push_back(in[n - 1][j].front());
        in[n - 1][j].pop_front();
      }
    }
  }
  for (int j = 1; j < m; ++j) {
    while (!in[0][j].empty()) {
      moves.push_back(Move(0, j, 0, 0));
      in[0][j].pop_back();
    }
    while (!in[n - 1][j].empty()) {
      moves.push_back(Move(n - 1, j, n - 1, 0));
      in[n - 1][j].pop_back();
    }
  }
  return moves;
}
int main() {
  scanf("%d%d", &n, &m);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      scanf("%s", buf);
      int len = strlen(buf);
      for (int k = 0; k < len; ++k) start[i][j].push_back(buf[k] - '0');
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      scanf("%s", buf);
      int len = strlen(buf);
      for (int k = 0; k < len; ++k) stop[i][j].push_back(buf[k] - '0');
    }
  }
  auto as = CanonES(start);
  auto ae = CanonSE(stop);
  while (!ae.empty()) {
    auto cur = ae.back();
    ae.pop_back();
    as.push_back(Move(cur.x2, cur.y2, cur.x1, cur.y1));
  }
  printf("%d\n", ((int)(as).size()));
  for (int i = 0; i < ((int)(as).size()); ++i)
    printf("%d %d %d %d\n", as[i].x1 + 1, as[i].y1 + 1, as[i].x2 + 1,
           as[i].y2 + 1);
  return 0;
}
