#include <bits/stdc++.h>
using namespace std;
using namespace rel_ops;
using ll = int64_t;
using Pii = pair<int, int>;
using ull = uint64_t;
using Vi = vector<int>;
void run();
int main() {
  cin.sync_with_stdio(0);
  cin.tie(0);
  cout << fixed << setprecision(10);
  run();
  return 0;
}
int uplg(int n) { return 32 - __builtin_clz(n); }
int uplg(ll n) { return 64 - __builtin_clzll(n); }
int cmp(double a, double b, double eps = 1e-9) {
  return (a > b + eps) - (a + eps < b);
}
using Move = pair<Pii, Pii>;
int n, m;
void simulate(vector<vector<string>>& board,
              const vector<vector<string>>& expected, vector<Move> moves) {
  for (int i = (0); i < (n); i++) {
    for (int j = (0); j < (m); j++) cerr << board[i][j] << ' ';
    cerr << '\n';
  }
  cerr << '\n';
  for (auto& mv : (moves)) {
    assert(mv.first != mv.second);
    auto& src = board[mv.first.first][mv.first.second];
    assert(!src.empty());
    char chr = src[0];
    src.erase(src.begin());
    auto& dst = board[mv.second.first][mv.second.second];
    dst.push_back(chr);
    ;
    for (int i = (0); i < (n); i++) {
      for (int j = (0); j < (m); j++) cerr << board[i][j] << ' ';
      cerr << '\n';
    }
    cerr << '\n';
  }
  for (int i = (0); i < (n); i++) {
    for (int j = (0); j < (m); j++) {
      assert(board[i][j] == expected[i][j]);
    }
    cerr << '\n';
  }
  cerr << '\n';
}
vector<Move> getMoves(vector<vector<string>>& board) {
  vector<Move> moves;
  for (auto& c : (board[0][0])) {
    if (c == '0') {
      moves.push_back({{0, 0}, {1, 0}});
      moves.push_back({{1, 0}, {0, 0}});
    } else {
      moves.push_back({{0, 1}, {0, 0}});
    }
  }
  for (auto& c : (board[0][1])) {
    if (c == '1') {
      moves.push_back({{0, 1}, {1, 1}});
      moves.push_back({{1, 1}, {0, 1}});
    } else {
      moves.push_back({{0, 0}, {0, 1}});
    }
  }
  for (int i = (1); i < (n); i++) {
    for (auto& c : (board[i][0]))
      if (c == '1') moves.push_back({{0, 1}, {i, 1}});
    for (auto& c : (board[i][1]))
      if (c == '0') moves.push_back({{0, 0}, {i, 0}});
    for (auto& c : (board[i][0])) {
      if (c == '0') {
        moves.push_back({{0, 0}, {i, 0}});
      } else {
        moves.push_back({{i, 1}, {i, 0}});
      }
    }
    for (auto& c : (board[i][1])) {
      if (c == '1') {
        moves.push_back({{0, 1}, {i, 1}});
      } else {
        moves.push_back({{i, 0}, {i, 1}});
      }
    }
  }
  for (int i = n - 1; i >= 0; i--) {
    for (int j = (2); j < (m); j++) {
      for (auto& c : (board[i][j])) {
        if (c == '0') {
          moves.push_back({{0, 0}, {0, j}});
        } else {
          moves.push_back({{0, 1}, {0, j}});
        }
        if (i > 0) {
          moves.push_back({{0, j}, {i, j}});
        }
      }
    }
  }
  return moves;
}
void run() {
  cin >> n >> m;
  vector<vector<string>> starting(n, vector<string>(m));
  vector<vector<string>> target(n, vector<string>(m));
  for (int i = (0); i < (n); i++)
    for (int j = (0); j < (m); j++) cin >> starting[i][j];
  for (int i = (0); i < (n); i++)
    for (int j = (0); j < (m); j++)
      cin >> target[i][j],
          reverse((target[i][j]).begin(), (target[i][j]).end());
  vector<Move> first = getMoves(starting);
  vector<Move> second = getMoves(target);
  reverse((first).begin(), (first).end());
  for (auto& mv : (first)) swap(mv.first, mv.second);
  first.insert(first.end(), (second).begin(), (second).end());
  cout << int((first).size()) << endl;
  for (auto& mv : (first)) {
    cout << mv.first.first + 1 << ' ' << mv.first.second + 1 << ' '
         << mv.second.first + 1 << ' ' << mv.second.second + 1 << '\n';
  }
}
