#include <bits/stdc++.h>
#define REP(i, n) for(int i = 0; i < n; i++)
#define REPR(i, n) for(int i = n; i >= 0; i--)
#define FOR(i, m, n) for(int i = m; i < n; i++)
#define INF 2e9
#define MOD 1000000007
#define ALL(v) v.begin(), v.end()
using namespace std;
typedef long long ll;
using P = pair<int,int>;

int main()
{
  int H,W;
  cin >> H >> W;
  vector<vector<int>> A(H,vector<int>(W));
  REP(i, H){
    REP(j, W){
      cin >> A.at(i).at(j);
    }
  }

  vector<vector<int>> ans(4,vector<int> ());
  int flag = 0;
  REP(i,H){
    if(i%2==0){
      REP(j,W){
        if(A.at(i).at(j)%2==1&&flag==0){
          flag=1;
          continue;
        }
        if(flag==1){
          ans.at(2).push_back(i);
          ans.at(3).push_back(j);
          if(j==0){
            ans.at(0).push_back(i-1);
            ans.at(1).push_back(j);
          }else{
            ans.at(0).push_back(i);
            ans.at(1).push_back(j-1);
          }
        }
        if(A.at(i).at(j)%2==1&&flag==1){
          flag=0;
        }
      }
    }else{
      REPR(j,W-1){
        if(A.at(i).at(j)%2==1&&flag==0){
          flag=1;
          continue;
        }
        if(flag==1){
          ans.at(2).push_back(i);
          ans.at(3).push_back(j);
          if(j==W-1){
            ans.at(0).push_back(i-1);
            ans.at(1).push_back(j);
          }else{
            ans.at(0).push_back(i);
            ans.at(1).push_back(j+1);
          }
        }
        if(A.at(i).at(j)%2==1&&flag==1){
          flag=0;
        }
      }
    }
  }

  cout << ans.at(0).size() << endl;
  REP(i,ans.at(0).size()){
    REP(j,3){
      cout << ++ans.at(j).at(i) << " ";
    }
    cout << ++ans.at(3).at(i) << endl;
  }
}
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <vector>
#include <queue>
#include <bitset>
#include <string>
using namespace std;

#define REP(i,n) for(int i=0; i<n; i++)
#define RPA(i,s,e) for(int i=s; i<=e; i++)
#define RPD(i,s,e) for(int i=s; i>=e; i--)
#define PB(a) push_back(a)
#define MP(i,s) make_pair(i,s)
#define ALL(a) (a).begin(), (a).end()
#define PRT(a) cout << (a) << endl

typedef pair<int,int> P;

const int INF = 1000000009;
const int MAX_V = 101;
struct edge { int to, cost; };
vector<edge> G[MAX_V];

int N,K,L;
int f,t,c;
int dist[MAX_V];

void add_edge(int from, int to, int cost) {
	edge e1 = { to, cost };
	edge e2 = { from, cost };
	G[from].PB(e1);
	G[to].PB(e2);
}

int dijkstra(int from, int to) {
	fill(dist, dist+MAX_V, INF);
	priority_queue<P, vector<P>, greater<P> > que;
	dist[from] = 0;
	que.push(MP(0, from));
	while(!que.empty()) {
		P p = que.top();
		que.pop();

		int v = p.second;
		if(dist[v] < p.first) continue;

		REP(i,G[v].size()) {
			edge& e = G[v][i];
			if(dist[e.to] > dist[v] + e.cost) {
				dist[e.to] = dist[v] + e.cost;
				que.push(MP(dist[e.to], e.to));
			}
		}
	}

	return dist[to] == INF ? -1 : dist[to];
}

void coding() {
	while(scanf("%d%d", &N, &K) != EOF) {
		REP(i,N) G[i].clear();
		REP(i,K) {
			scanf("%d", &L);
			if(L == 0) {
				scanf("%d%d", &f, &t);
				f--; t--;
				printf("%d\n", dijkstra(f, t));
			} else if(L == 1) {
				scanf("%d%d%d", &f, &t, &c);
				f--; t--;
				add_edge(f, t, c);
			} else {
				PRT("unknown");
			}
		}
	}
}

// #define _LOCAL_TEST

int main() {
#ifdef _LOCAL_TEST
	clock_t startTime = clock();
	freopen("a.in", "r", stdin);
#endif

	coding();

#ifdef _LOCAL_TEST
	clock_t elapsedTime = clock() - startTime;
	cout << endl;
	cout << (elapsedTime / 1000.0) << " sec elapsed." << endl;
	cout << "This is local test" << endl;
	cout << "Do not forget to comment out _LOCAL_TEST" << endl << endl;
#endif
}