import java.util.*;
import java.io.*;
public class EdA {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static int[][] grid;
    static int[][] newgrid;
    static ArrayList<Operation> array;
    static int n;
    static int m;
    public static void run(){
    	for(int j = 0;j+1<n;j+=2){
 			for(int k = 0;k+1<m;k+=2){

 					if (j+1 < n && k+1 < m){
 						fix(j, k);
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 						grid[j][k+1] = 0;
 						grid[j+1][k+1] = 0;
 					}
 					else if (j+1 < n && k-1 >=0){
 						fix(j, k-1);
 						grid[j][k-1] = 0;
 						grid[j+1][k-1] = 0;
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 					}
 					else if (j-1 >=0 && k+1 < m){
 						fix(j-1, k);
 						grid[j-1][k] = 0;
 						grid[j-1][k+1] = 0;
 						grid[j][k] = 0;
 						grid[j][k+1] = 0;
 					}
 					else if (j-1 >=0 && k-1>=0){
 						fix(j-1, k-1);
 						grid[j-1][k-1] = 0;
 						grid[j-1][k] = 0;
 						grid[j][k-1] = 0;
 						grid[j][k] = 0;
 					}

 			}
 		}
    }

	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);
 		int t = sc.nextInt();
 		for(int i = 0;i<t;i++){
//	 		String input1 = bf.readLine().trim();
//	 		String input2 = bf.readLine().trim();
//			COMPARING INTEGER OBJECTS U DO DOT EQUALS NOT ==
	 		n = sc.nextInt();
	 		m = sc.nextInt();
	 		grid = new int[n][m];
	 		array = new ArrayList<Operation>();
	 		newgrid = new int[n][m];
	 		for(int j =0 ;j<n;j++){
	 			String s = sc.next();
	 			for(int k = 0;k<m;k++){
	 				grid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 				newgrid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 			}
	 		}
	 		if (n%2 == 1 && m%2 == 1){
	 			if (grid[n-1][m-1] == 1)
	 				z11(n-2, m-2);
	 		}
	 		if (m%2 == 1){
	 			for(int j = n-2;j>0;j--)
	 				if (grid[j][m-1] == 1)
	 					z10(j-1, m-2);
	 			if (grid[0][m-1] == 1)
	 				z00(0, m-2);
	 		}
	 		if (n%2 == 1){
	 			for(int j = m-2;j>0;j--)
	 				if (grid[n-1][j] == 1)
	 					z01(n-2, j-1);
	 			if (grid[n-1][0] == 1)
	 				z00(n-2, 0);
	 		}
	 		run();
	 		out.println(array.size());
	 		for(Operation j : array){
	 			out.println((j.x1+1) + " " + (j.y1+1) + " " + (j.x2+1) + " " + (j.y2+1) + " " + (j.x3+1) + " " + (j.y3+1));
	 		}

//	 		for(int j = 0;j<array.length;j++){
//	 			out.print(array[j] + " ");
//	 		}
//	 		out.println();
 		}
 		out.println();

 		out.close();
 	}
	public static void fix(int r, int c){
		int count = 0;
		if (grid[r][c] == 1)
			count++;
		if (grid[r+1][c] == 1)
			count++;
		if (grid[r][c+1] == 1)
			count++;
		if (grid[r+1][c+1] == 1)
			count++;

		if (count == 1){
			if (grid[r][c] == 1){
				z00(r, c);
				z10(r, c);
				z01(r, c);
			}
			if (grid[r+1][c] == 1){
				z00(r, c);
				z10(r, c);
				z11(r, c);
			}
			if (grid[r][c+1] == 1){
				z00(r, c);
				z01(r, c);
				z11(r, c);
			}
			if (grid[r+1][c+1] == 1){
				z10(r, c);
				z01(r, c);
				z11(r, c);
			}
		}
		else if (count == 2){
			if (grid[r][c] == 1 && grid[r+1][c] == 1){
				z01(r, c);
				z11(r, c);
			}
			if (grid[r+1][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z01(r, c);
			}
			if (grid[r+1][c+1] == 1 && grid[r][c+1] == 1){
				z00(r, c);
				z10(r, c);
			}
			if (grid[r][c+1] == 1 && grid[r][c] == 1){
				z10(r, c);
				z11(r, c);
			}
			if (grid[r][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z11(r, c);
			}
			if (grid[r+1][c] == 1 && grid[r][c+1] == 1){
				z10(r, c);
				z01(r, c);
			}

		}
		else if (count == 3){
			if (grid[r][c] == 0){
				z11(r, c);
			}
			if (grid[r+1][c] == 0){
				z01(r, c);
			}
			if (grid[r][c+1] == 0){
				z10(r, c);
			}
			if (grid[r+1][c+1] == 0){
				z00(r, c);
			}
		}
		else if (count == 4){
			z00(r, c);
			z11(r, c);
			z01(r, c);
			z10(r, c);
		}
	}

	public static void z00(int r, int c){
		array.add(new Operation(r, c, r+1, c, r, c+1));
	}
	public static void z01(int r, int c){
		array.add(new Operation(r, c+1, r, c, r+1, c+1));
	}
	public static void z10(int r, int c){
		array.add(new Operation(r+1, c, r, c, r+1, c+1));
	}
	public static void z11(int r, int c){
		array.add(new Operation(r+1, c+1, r+1, c, r, c+1));
	}
	static class Operation{
		private int x1;
		private int y1;
		private int x2;
		private int y2;
		private int x3;
		private int y3;
		public Operation(int x1, int y1, int x2, int y2, int x3, int y3){
			this.x1 = x1;
			this.x2 = x2;
			this.x3 = x3;
			this.y1 = y1;
			this.y2 = y2;
			this.y3 = y3;
		}
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.util.*;
import java.io.*;
public class EdA {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static int[][] grid;
    static int[][] newgrid;
    static ArrayList<Operation> array;
    static int n;
    static int m;
    public static void run(){
    	for(int j = 0;j+1<n;j+=2){
 			for(int k = 0;k+1<m;k+=2){

 					if (j+1 < n && k+1 < m){
 						fix(j, k);
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 						grid[j][k+1] = 0;
 						grid[j+1][k+1] = 0;
 					}
 					else if (j+1 < n && k-1 >=0){
 						fix(j, k-1);
 						grid[j][k-1] = 0;
 						grid[j+1][k-1] = 0;
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 					}
 					else if (j-1 >=0 && k+1 < m){
 						fix(j-1, k);
 						grid[j-1][k] = 0;
 						grid[j-1][k+1] = 0;
 						grid[j][k] = 0;
 						grid[j][k+1] = 0;
 					}
 					else if (j-1 >=0 && k-1>=0){
 						fix(j-1, k-1);
 						grid[j-1][k-1] = 0;
 						grid[j-1][k] = 0;
 						grid[j][k-1] = 0;
 						grid[j][k] = 0;
 					}

 			}
 		}
    }

	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);
 		int t = sc.nextInt();
 		for(int i = 0;i<t;i++){
//	 		String input1 = bf.readLine().trim();
//	 		String input2 = bf.readLine().trim();
//			COMPARING INTEGER OBJECTS U DO DOT EQUALS NOT ==
	 		n = sc.nextInt();
	 		m = sc.nextInt();
	 		grid = new int[n][m];
	 		array = new ArrayList<Operation>();
	 		newgrid = new int[n][m];
	 		for(int j =0 ;j<n;j++){
	 			String s = sc.next();
	 			for(int k = 0;k<m;k++){
	 				grid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 				newgrid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 			}
	 		}
	 		if (n%2 == 1 || m%2 == 1){
	 			if (grid[n-1][m-1] == 1){
	 				z11(n-2, m-2);
	 			}
	 		}
	 		if (m%2 == 1){
	 			for(int j = n-2;j>0;j--){
	 				if (grid[j][m-1] == 1){
	 					z10(j-1, m-2);
	 				}
	 			}
	 			if (grid[0][m-1] == 1){
	 				z00(0, m-2);
	 			}
	 		}
	 		if (n%2 == 1){
	 			for(int j = m-2;j>0;j--){
	 				if (grid[n-1][j] == 1){
	 					z01(n-2, j-1);
	 				}
	 			}
	 			if (grid[n-1][0] == 1){
	 				z00(n-2, 0);
	 			}
	 		}
	 		run();
	 		out.println(array.size());
	 		for(Operation j : array){
	 			out.println((j.x1+1) + " " + (j.y1+1) + " " + (j.x2+1) + " " + (j.y2+1) + " " + (j.x3+1) + " " + (j.y3+1));
	 		}

//	 		for(int j = 0;j<array.length;j++){
//	 			out.print(array[j] + " ");
//	 		}
//	 		out.println();
 		}
 		out.println();

 		out.close();
 	}
	public static void fix(int r, int c){
		int count = 0;
		if (grid[r][c] == 1)
			count++;
		if (grid[r+1][c] == 1)
			count++;
		if (grid[r][c+1] == 1)
			count++;
		if (grid[r+1][c+1] == 1)
			count++;

		if (count == 1){
			if (grid[r][c] == 1){
				z00(r, c);
				z10(r, c);
				z01(r, c);
			}
			else if (grid[r+1][c] == 1){
				z00(r, c);
				z10(r, c);
				z11(r, c);
			}
			else if (grid[r][c+1] == 1){
				z00(r, c);
				z01(r, c);
				z11(r, c);
			}
			else if (grid[r+1][c+1] == 1){
				z10(r, c);
				z01(r, c);
				z11(r, c);
			}
		}
		else if (count == 2){
			if (grid[r][c] == 1 && grid[r+1][c] == 1){
				z01(r, c);
				z11(r, c);
			}
			else if (grid[r+1][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z01(r, c);
			}
			else if (grid[r+1][c+1] == 1 && grid[r][c+1] == 1){
				z00(r, c);
				z10(r, c);
			}
			else if (grid[r][c+1] == 1 && grid[r][c] == 1){
				z10(r, c);
				z11(r, c);
			}
			else if (grid[r][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z11(r, c);
			}
			else if (grid[r+1][c] == 1 && grid[r][c+1] == 1){
				z10(r, c);
				z01(r, c);
			}

		}
		else if (count == 3){
			if (grid[r][c] == 0){
				z11(r, c);
			}
			else if (grid[r+1][c] == 0){
				z01(r, c);
			}
			else if (grid[r][c+1] == 0){
				z10(r, c);
			}
			else if (grid[r+1][c+1] == 0){
				z00(r, c);
			}
		}
		else if (count == 4){
			z00(r, c);
			z11(r, c);
			z01(r, c);
			z10(r, c);
		}
	}

	public static void z00(int r, int c){
		array.add(new Operation(r, c, r+1, c, r, c+1));
		grid[r][c] = 1-grid[r][c];
		grid[r+1][c] = 1-grid[r+1][c];
		grid[r][c+1] = 1-grid[r][c+1];
	}
	public static void z01(int r, int c){
		array.add(new Operation(r, c+1, r, c, r+1, c+1));
		grid[r][c] = 1-grid[r][c];
		grid[r][c+1] = 1-grid[r][c+1];
		grid[r+1][c+1] = 1-grid[r+1][c+1];
	}
	public static void z10(int r, int c){
		array.add(new Operation(r+1, c, r, c, r+1, c+1));
		grid[r][c] = 1-grid[r][c];
		grid[r+1][c] = 1-grid[r+1][c];
		grid[r+1][c+1] = 1-grid[r+1][c+1];
	}
	public static void z11(int r, int c){
		array.add(new Operation(r+1, c+1, r+1, c, r, c+1));
		grid[r+1][c] = 1-grid[r+1][c];
		grid[r][c+1] = 1-grid[r][c+1];
		grid[r+1][c+1] = 1-grid[r+1][c+1];
	}
	static class Operation{
		private int x1;
		private int y1;
		private int x2;
		private int y2;
		private int x3;
		private int y3;
		public Operation(int x1, int y1, int x2, int y2, int x3, int y3){
			this.x1 = x1;
			this.x2 = x2;
			this.x3 = x3;
			this.y1 = y1;
			this.y2 = y2;
			this.y3 = y3;
		}
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.util.*;
import java.io.*;
public class EdA {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static int[][] grid;
    static int[][] newgrid;
    static ArrayList<Operation> array;
    static int n;
    static int m;
    public static void run(){
    	for(int j = 0;j+1<n;j+=2){
 			for(int k = 0;k+1<m;k+=2){

 					if (j+1 < n && k+1 < m){
 						fix(j, k);
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 						grid[j][k+1] = 0;
 						grid[j+1][k+1] = 0;
 					}
 					else if (j+1 < n && k-1 >=0){
 						fix(j, k-1);
 						grid[j][k-1] = 0;
 						grid[j+1][k-1] = 0;
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 					}
 					else if (j-1 >=0 && k+1 < m){
 						fix(j-1, k);
 						grid[j-1][k] = 0;
 						grid[j-1][k+1] = 0;
 						grid[j][k] = 0;
 						grid[j][k+1] = 0;
 					}
 					else if (j-1 >=0 && k-1>=0){
 						fix(j-1, k-1);
 						grid[j-1][k-1] = 0;
 						grid[j-1][k] = 0;
 						grid[j][k-1] = 0;
 						grid[j][k] = 0;
 					}

 			}
 		}
    }

	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);
 		int t = sc.nextInt();
 		for(int i = 0;i<t;i++){
//	 		String input1 = bf.readLine().trim();
//	 		String input2 = bf.readLine().trim();
//			COMPARING INTEGER OBJECTS U DO DOT EQUALS NOT ==
	 		n = sc.nextInt();
	 		m = sc.nextInt();
	 		grid = new int[n][m];
	 		array = new ArrayList<Operation>();
	 		newgrid = new int[n][m];
	 		for(int j =0 ;j<n;j++){
	 			String s = sc.next();
	 			for(int k = 0;k<m;k++){
	 				grid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 				newgrid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 			}
	 		}
	 		if (n%2 == 1 && m%2 == 1){
	 			if (grid[n-1][m-1] == 1){
	 				z11(n-2, m-2);
	 			}
	 		}
	 		if (m%2 == 1){
	 			for(int j = n-2;j>0;j--){
	 				if (grid[j][m-1] == 1){
	 					z10(j-1, m-2);
	 				}
	 			}
	 			if (grid[0][m-1] == 1){
	 				z00(0, m-2);
	 			}
	 		}
	 		if (n%2 == 1){
	 			for(int j = m-2;j>0;j--){
	 				if (grid[n-1][j] == 1){
	 					z01(n-2, j-1);
	 				}
	 			}
	 			if (grid[n-1][0] == 1){
	 				z00(n-2, 0);
	 			}
	 		}
	 		run();
	 		out.println(array.size());
	 		for(Operation j : array){
	 			out.println((j.x1+1) + " " + (j.y1+1) + " " + (j.x2+1) + " " + (j.y2+1) + " " + (j.x3+1) + " " + (j.y3+1));
	 		}

//	 		for(int j = 0;j<array.length;j++){
//	 			out.print(array[j] + " ");
//	 		}
//	 		out.println();
 		}
 		out.println();

 		out.close();
 	}
	public static void fix(int r, int c){
		int count = 0;
		if (grid[r][c] == 1)
			count++;
		if (grid[r+1][c] == 1)
			count++;
		if (grid[r][c+1] == 1)
			count++;
		if (grid[r+1][c+1] == 1)
			count++;

		if (count == 1){
			if (grid[r][c] == 1){
				z00(r, c);
				z10(r, c);
				z01(r, c);
			}
			else if (grid[r+1][c] == 1){
				z00(r, c);
				z10(r, c);
				z11(r, c);
			}
			else if (grid[r][c+1] == 1){
				z00(r, c);
				z01(r, c);
				z11(r, c);
			}
			else if (grid[r+1][c+1] == 1){
				z10(r, c);
				z01(r, c);
				z11(r, c);
			}
		}
		else if (count == 2){
			if (grid[r][c] == 1 && grid[r+1][c] == 1){
				z01(r, c);
				z11(r, c);
			}
			else if (grid[r+1][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z01(r, c);
			}
			else if (grid[r+1][c+1] == 1 && grid[r][c+1] == 1){
				z00(r, c);
				z10(r, c);
			}
			else if (grid[r][c+1] == 1 && grid[r][c] == 1){
				z10(r, c);
				z11(r, c);
			}
			else if (grid[r][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z11(r, c);
			}
			else if (grid[r+1][c] == 1 && grid[r][c+1] == 1){
				z10(r, c);
				z01(r, c);
			}

		}
		else if (count == 3){
			if (grid[r][c] == 0){
				z11(r, c);
			}
			else if (grid[r+1][c] == 0){
				z01(r, c);
			}
			else if (grid[r][c+1] == 0){
				z10(r, c);
			}
			else if (grid[r+1][c+1] == 0){
				z00(r, c);
			}
		}
		else if (count == 4){
			z00(r, c);
			z11(r, c);
			z01(r, c);
			z10(r, c);
		}
	}

	public static void z00(int r, int c){
		array.add(new Operation(r, c, r+1, c, r, c+1));
		grid[r][c] = 1-grid[r][c];
		grid[r+1][c] = 1-grid[r+1][c];
		grid[r][c+1] = 1-grid[r][c+1];
	}
	public static void z01(int r, int c){
		array.add(new Operation(r, c+1, r, c, r+1, c+1));
		grid[r][c] = 1-grid[r][c];
		grid[r][c+1] = 1-grid[r][c+1];
		grid[r+1][c+1] = 1-grid[r+1][c+1];
	}
	public static void z10(int r, int c){
		array.add(new Operation(r+1, c, r, c, r+1, c+1));
		grid[r][c] = 1-grid[r][c];
		grid[r+1][c] = 1-grid[r+1][c];
		grid[r+1][c+1] = 1-grid[r+1][c+1];
	}
	public static void z11(int r, int c){
		array.add(new Operation(r+1, c+1, r+1, c, r, c+1));
		grid[r+1][c] = 1-grid[r+1][c];
		grid[r][c+1] = 1-grid[r][c+1];
		grid[r+1][c+1] = 1-grid[r+1][c+1];
	}
	static class Operation{
		private int x1;
		private int y1;
		private int x2;
		private int y2;
		private int x3;
		private int y3;
		public Operation(int x1, int y1, int x2, int y2, int x3, int y3){
			this.x1 = x1;
			this.x2 = x2;
			this.x3 = x3;
			this.y1 = y1;
			this.y2 = y2;
			this.y3 = y3;
		}
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.util.*;
import java.io.*;
public class EdA {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static int[][] grid;
    static int[][] newgrid;
    static ArrayList<Operation> array;
    static int n;
    static int m;
    public static void run(){
    	for(int j = 0;j<n;j+=2){
 			for(int k = 0;k<m;k+=2){

 					if (j+1 < n && k+1 < m){
 						fix(j, k);
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 						grid[j][k+1] = 0;
 						grid[j+1][k+1] = 0;
 					}
 					else if (j+1 < n && k-1 >=0){
 						fix(j, k-1);
 						grid[j][k-1] = 0;
 						grid[j+1][k-1] = 0;
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 					}
 					else if (j-1 >=0 && k+1 < m){
 						fix(j-1, k);
 						grid[j-1][k] = 0;
 						grid[j-1][k+1] = 0;
 						grid[j][k] = 0;
 						grid[j][k+1] = 0;
 					}
 					else if (j-1 >=0 && k-1>=0){
 						fix(j-1, k-1);
 						grid[j-1][k-1] = 0;
 						grid[j-1][k] = 0;
 						grid[j][k-1] = 0;
 						grid[j][k] = 0;
 					}

 			}
 		}
    }
	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);
 		int t = sc.nextInt();
 		for(int i = 0;i<t;i++){
//	 		String input1 = bf.readLine().trim();
//	 		String input2 = bf.readLine().trim();
//			COMPARING INTEGER OBJECTS U DO DOT EQUALS NOT ==
	 		n = sc.nextInt();
	 		m = sc.nextInt();
	 		grid = new int[n][m];
	 		newgrid = new int[n][m];
	 		for(int j =0 ;j<n;j++){
	 			String s = sc.next();
	 			for(int k = 0;k<m;k++){
	 				grid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 				newgrid[j][k] = 1-Integer.parseInt(s.charAt(k)+ "");
	 			}
	 		}
	 		array = new ArrayList<Operation>();
	 		run();
	 		if (array.size() > n*m){
	 			array.clear();
	 			grid = newgrid;
	 			run();
	 		}

	 		out.println(array.size());
	 		for(Operation j : array){
	 			out.println((j.x1+1)+ " " + (j.y1+1) + " " + (j.x2+1)+ " " + (j.y2+1) + " "+ (j.x3+1)+ " " + (j.y3+1) );
	 		}

//	 		for(int j = 0;j<array.length;j++){
//	 			out.print(array[j] + " ");
//	 		}
//	 		out.println();
 		}
 		out.println();

 		out.close();
 	}
	public static void fix(int r, int c){
		int count = 0;
		if (grid[r][c] == 1)
			count++;
		if (grid[r+1][c] == 1)
			count++;
		if (grid[r][c+1] == 1)
			count++;
		if (grid[r+1][c+1] == 1)
			count++;

		if (count == 1){
			if (grid[r][c] == 1){
				z00(r, c);
				z10(r, c);
				z01(r, c);
			}
			if (grid[r+1][c] == 1){
				z00(r, c);
				z10(r, c);
				z11(r, c);
			}
			if (grid[r][c+1] == 1){
				z00(r, c);
				z01(r, c);
				z11(r, c);
			}
			if (grid[r+1][c+1] == 1){
				z10(r, c);
				z01(r, c);
				z11(r, c);
			}
		}
		else if (count == 2){
			if (grid[r][c] == 1 && grid[r+1][c] == 1){
				z01(r, c);
				z11(r, c);
			}
			if (grid[r+1][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z01(r, c);
			}
			if (grid[r+1][c+1] == 1 && grid[r][c+1] == 1){
				z00(r, c);
				z10(r, c);
			}
			if (grid[r][c+1] == 1 && grid[r][c] == 1){
				z10(r, c);
				z11(r, c);
			}
			if (grid[r][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z11(r, c);
			}
			if (grid[r+1][c] == 1 && grid[r][c+1] == 1){
				z10(r, c);
				z01(r, c);
			}

		}
		else if (count == 3){
			if (grid[r][c] == 0){
				z11(r, c);
			}
			if (grid[r+1][c] == 0){
				z01(r, c);
			}
			if (grid[r][c+1] == 0){
				z10(r, c);
			}
			if (grid[r+1][c+1] == 0){
				z00(r, c);
			}
		}
		else if (count == 4){
			z00(r, c);
			z11(r, c);
			z01(r, c);
			z10(r, c);
		}
	}
	public static void z00(int r, int c){
		array.add(new Operation(r, c, r+1, c, r, c+1));
	}
	public static void z01(int r, int c){
		array.add(new Operation(r, c+1, r, c, r+1, c+1));
	}
	public static void z10(int r, int c){
		array.add(new Operation(r+1, c, r, c, r+1, c+1));
	}
	public static void z11(int r, int c){
		array.add(new Operation(r+1, c+1, r+1, c, r, c+1));
	}
	static class Operation{
		private int x1;
		private int y1;
		private int x2;
		private int y2;
		private int x3;
		private int y3;
		public Operation(int x1, int y1, int x2, int y2, int x3, int y3){
			this.x1 = x1;
			this.x2 = x2;
			this.x3 = x3;
			this.y1 = y1;
			this.y2 = y2;
			this.y3 = y3;
		}
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.util.*;
import java.io.*;
public class EdA {
	static long[] mods = {1000000007, 998244353, 1000000009};
	static long mod = mods[0];
	public static MyScanner sc;
    public static PrintWriter out;
    static int[][] grid;
    static int[][] newgrid;
    static ArrayList<Operation> array;
    static int n;
    static int m;
    public static void run(){
    	for(int j = 0;j+1<n;j+=2){
 			for(int k = 0;k+1<m;k+=2){

 					if (j+1 < n && k+1 < m){
 						fix(j, k);
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 						grid[j][k+1] = 0;
 						grid[j+1][k+1] = 0;
 					}
 					else if (j+1 < n && k-1 >=0){
 						fix(j, k-1);
 						grid[j][k-1] = 0;
 						grid[j+1][k-1] = 0;
 						grid[j][k] = 0;
 						grid[j+1][k] = 0;
 					}
 					else if (j-1 >=0 && k+1 < m){
 						fix(j-1, k);
 						grid[j-1][k] = 0;
 						grid[j-1][k+1] = 0;
 						grid[j][k] = 0;
 						grid[j][k+1] = 0;
 					}
 					else if (j-1 >=0 && k-1>=0){
 						fix(j-1, k-1);
 						grid[j-1][k-1] = 0;
 						grid[j-1][k] = 0;
 						grid[j][k-1] = 0;
 						grid[j][k] = 0;
 					}

 			}
 		}
    }

	public static void main(String[] omkar) throws Exception{
		// TODO Auto-generated method stub
 		sc = new MyScanner();
 		out = new PrintWriter(System.out);
 		int t = sc.nextInt();
 		for(int i = 0;i<t;i++){
//	 		String input1 = bf.readLine().trim();
//	 		String input2 = bf.readLine().trim();
//			COMPARING INTEGER OBJECTS U DO DOT EQUALS NOT ==
	 		n = sc.nextInt();
	 		m = sc.nextInt();
	 		grid = new int[n][m];
	 		array = new ArrayList<Operation>();
	 		newgrid = new int[n][m];
	 		for(int j =0 ;j<n;j++){
	 			String s = sc.next();
	 			for(int k = 0;k<m;k++){
	 				grid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 				newgrid[j][k] = Integer.parseInt(s.charAt(k)+ "");
	 			}
	 		}
	 		if (n%2 == 1 && m%2 == 1){
	 			if (grid[n-1][m-1] == 1){
	 				z11(n-2, m-2);
	 				grid[n-1][m-1] = 1-grid[n-1][m-1];
	 				grid[n-2][m-1] = 1-grid[n-2][m-1];
	 				grid[n-1][m-2] = 1-grid[n-1][m-2];
	 			}
	 		}
	 		if (m%2 == 1){
	 			for(int j = n-2;j>0;j--){
	 				if (grid[j][m-1] == 1){
	 					z10(j-1, m-2);
	 					grid[j][m-2] = 1-grid[j][m-2];
		 				grid[j-1][m-2] = 1-grid[j-1][m-2];
		 				grid[j][m-1] = 1-grid[j][m-1];
	 				}
	 			}
	 			if (grid[0][m-1] == 1){
	 				z00(0, m-2);
	 				grid[0][m-2] = 1-grid[0][m-2];
	 				grid[1][m-2] = 1-grid[1][m-2];
	 				grid[0][m-1] = 1-grid[0][m-1];
	 			}
	 		}
	 		if (n%2 == 1){
	 			for(int j = m-2;j>0;j--){
	 				if (grid[n-1][j] == 1){
	 					z01(n-2, j-1);
	 					grid[n-2][j] = 1-grid[n-2][j];
	 					grid[n-1][j] = 1-grid[n-1][j];
	 					grid[n-2][j-1] = 1-grid[n-2][j-1];
	 				}
	 			}
	 			if (grid[n-1][0] == 1){
	 				z00(n-2, 0);
	 				grid[n-2][0] = 1-grid[n-2][0];
	 				grid[n-2][1] = 1-grid[n-2][1];
	 				grid[n-1][0] = 1-grid[n-1][0];
	 			}
	 		}
	 		run();
	 		out.println(array.size());
	 		for(Operation j : array){
	 			out.println((j.x1+1) + " " + (j.y1+1) + " " + (j.x2+1) + " " + (j.y2+1) + " " + (j.x3+1) + " " + (j.y3+1));
	 		}

//	 		for(int j = 0;j<array.length;j++){
//	 			out.print(array[j] + " ");
//	 		}
//	 		out.println();
 		}
 		out.println();

 		out.close();
 	}
	public static void fix(int r, int c){
		int count = 0;
		if (grid[r][c] == 1)
			count++;
		if (grid[r+1][c] == 1)
			count++;
		if (grid[r][c+1] == 1)
			count++;
		if (grid[r+1][c+1] == 1)
			count++;

		if (count == 1){
			if (grid[r][c] == 1){
				z00(r, c);
				z10(r, c);
				z01(r, c);
			}
			if (grid[r+1][c] == 1){
				z00(r, c);
				z10(r, c);
				z11(r, c);
			}
			if (grid[r][c+1] == 1){
				z00(r, c);
				z01(r, c);
				z11(r, c);
			}
			if (grid[r+1][c+1] == 1){
				z10(r, c);
				z01(r, c);
				z11(r, c);
			}
		}
		else if (count == 2){
			if (grid[r][c] == 1 && grid[r+1][c] == 1){
				z01(r, c);
				z11(r, c);
			}
			if (grid[r+1][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z01(r, c);
			}
			if (grid[r+1][c+1] == 1 && grid[r][c+1] == 1){
				z00(r, c);
				z10(r, c);
			}
			if (grid[r][c+1] == 1 && grid[r][c] == 1){
				z10(r, c);
				z11(r, c);
			}
			if (grid[r][c] == 1 && grid[r+1][c+1] == 1){
				z00(r, c);
				z11(r, c);
			}
			if (grid[r+1][c] == 1 && grid[r][c+1] == 1){
				z10(r, c);
				z01(r, c);
			}

		}
		else if (count == 3){
			if (grid[r][c] == 0){
				z11(r, c);
			}
			if (grid[r+1][c] == 0){
				z01(r, c);
			}
			if (grid[r][c+1] == 0){
				z10(r, c);
			}
			if (grid[r+1][c+1] == 0){
				z00(r, c);
			}
		}
		else if (count == 4){
			z00(r, c);
			z11(r, c);
			z01(r, c);
			z10(r, c);
		}
	}

	public static void z00(int r, int c){
		array.add(new Operation(r, c, r+1, c, r, c+1));
	}
	public static void z01(int r, int c){
		array.add(new Operation(r, c+1, r, c, r+1, c+1));
	}
	public static void z10(int r, int c){
		array.add(new Operation(r+1, c, r, c, r+1, c+1));
	}
	public static void z11(int r, int c){
		array.add(new Operation(r+1, c+1, r+1, c, r, c+1));
	}
	static class Operation{
		private int x1;
		private int y1;
		private int x2;
		private int y2;
		private int x3;
		private int y3;
		public Operation(int x1, int y1, int x2, int y2, int x3, int y3){
			this.x1 = x1;
			this.x2 = x2;
			this.x3 = x3;
			this.y1 = y1;
			this.y2 = y2;
			this.y3 = y3;
		}
	}
	public static void sort(int[] array){
		ArrayList<Integer> copy = new ArrayList<Integer>();
		for (int i : array)
			copy.add(i);
		Collections.sort(copy);
		for(int i = 0;i<array.length;i++)
			array[i] = copy.get(i);
	}
	static String[] readArrayString(int n){
		String[] array = new String[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.next();
		return array;
	}
	static int[] readArrayInt(int n){
    	int[] array = new int[n];
    	for(int j = 0;j<n;j++)
    		array[j] = sc.nextInt();
    	return array;
    }
	static int[] readArrayInt1(int n){
		int[] array = new int[n+1];
		for(int j = 1;j<=n;j++){
			array[j] = sc.nextInt();
		}
		return array;
	}
	static long[] readArrayLong(int n){
		long[] array = new long[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextLong();
		return array;
	}
	static double[] readArrayDouble(int n){
		double[] array = new double[n];
		for(int j =0 ;j<n;j++)
			array[j] = sc.nextDouble();
		return array;
	}
	static int minIndex(int[] array){
		int minValue = Integer.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(long[] array){
		long minValue = Long.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static int minIndex(double[] array){
		double minValue = Double.MAX_VALUE;
		int minIndex = -1;
		for(int j = 0;j<array.length;j++){
			if (array[j] < minValue){
				minValue = array[j];
				minIndex = j;
			}
		}
		return minIndex;
	}
	static long power(long x, long y){
		if (y == 0)
			return 1;
		if (y%2 == 1)
			return (x*power(x, y-1))%mod;
		return power((x*x)%mod, y/2)%mod;
	}
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;
        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int nextInt() {
            return Integer.parseInt(next());
        }
        long nextLong() {
            return Long.parseLong(next());
        }
        double nextDouble() {
            return Double.parseDouble(next());
        }
        String nextLine() {
            String str = "";
            try{
                str = br.readLine();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

    }
}

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


//make sure to make new file!
import java.io.*;
import java.util.*;

public class A684b{

   public static ArrayList<Move> answer;
   public static int n;
   public static int m;

   public static int[][] board;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      int t = Integer.parseInt(f.readLine());

      for(int q = 1; q <= t; q++){

         StringTokenizer st = new StringTokenizer(f.readLine());

         n = Integer.parseInt(st.nextToken());
         m = Integer.parseInt(st.nextToken());

         board = new int[n][m];
         for(int k = 0; k < n; k++){
            char[] c = f.readLine().toCharArray();
            for(int j = 0; j < m; j++){
               board[k][j] = Character.getNumericValue(c[j]);
            }
         }

         answer = new ArrayList<Move>();

         if(m%2 == 1){
            //make right column all 0
            for(int k = 0; k < n; k++){
               if(board[k][m-1] == 1){
                  if(k < n-1){
                     addmove(new Move(k,m-1,k,m-2,k+1,m-2));
                  } else {
                     addmove(new Move(k,m-1,k,m-2,k-1,m-2));
                  }
               }
            }
            m--;
         }

         for(int j = 0; j < m; j += 2){
            for(int k = 0; k < n-2; k++){
               if(board[k][j] == 1){
                  addmove(new Move(k,j,k+1,j,k+1,j+1));
               }
               if(board[k][j+1] == 1){
                  addmove(new Move(k,j+1,k+1,j+1,k+1,j));
               }
            }
            //last 2v2
            int num1 = 0;
            for(int a = n-2; a < n; a++){
               for(int b = j; b < j+2; b++){
                  if(board[a][b] == 1) num1++;
               }
            }

            if(num1 == 1) flip1(n-2,j);
            else if(num1 == 2) flip2(n-2,j);
            else if(num1 == 3) flip3(n-2,j);
            else if(num1 == 4) flip4(n-2,j);
         }

         out.println(answer.size());
         StringJoiner sj = new StringJoiner("\n");
         for(Move move : answer){
            sj.add(move.toString());
         }
         out.println(sj);

      }

      out.close();
   }

   public static void addmove(Move mv){
      board[mv.x1-1][mv.y1-1] ^= 1;
      board[mv.x2-1][mv.y2-1] ^= 1;
      board[mv.x3-1][mv.y3-1] ^= 1;
      answer.add(mv);
   }

   public static void flip1(int x, int y){
      if(board[x][y] == 1) fliptl(x,y);
      else if(board[x][y+1] == 1) fliptr(x,y);
      else if(board[x+1][y] == 1) flipbl(x,y);
      else flipbr(x,y);
   }

   public static void fliptl(int x, int y){
      answer.add(new Move(x,y,x,y+1,x+1,y+1));
      answer.add(new Move(x,y,x+1,y,x+1,y+1));
      answer.add(new Move(x,y,x+1,y,x,y+1));
   }

   public static void fliptr(int x, int y){
      answer.add(new Move(x,y,x,y-1,x+1,y-1));
      answer.add(new Move(x,y,x+1,y,x+1,y-1));
      answer.add(new Move(x,y,x+1,y,x,y-1));
   }

   public static void flipbl(int x, int y){
      answer.add(new Move(x,y,x,y+1,x-1,y+1));
      answer.add(new Move(x,y,x-1,y,x-1,y+1));
      answer.add(new Move(x,y,x-1,y,x,y+1));
   }

   public static void flipbr(int x, int y){
      answer.add(new Move(x,y,x,y-1,x-1,y-1));
      answer.add(new Move(x,y,x-1,y,x-1,y-1));
      answer.add(new Move(x,y,x-1,y,x,y-1));
   }

   public static void flip2(int x, int y){
      if(board[x][y] != board[x+1][y] && board[x][y] != board[x][y+1]){
         //diagonal
         if(board[x][y] == 1){
            addmove(new Move(x,y,x+1,y,x,y+1));
         } else {
            addmove(new Move(x,y+1,x,y,x+1,y+1));
         }
      } else {
         //2 in a row
         //pick a 0
         int x01 = -1;
         int y01 = -1;
         int x02 = -1;
         int y02 = -1;
         int nonex = -1;
         int noney = -1;
         for(int a = x; a <= x+1; a++){
            for(int b = y; b <= y+1; b++){
               if(board[a][b] == 0){
                  if(x01 == -1){
                     x01 = a;
                     y01 = b;
                  } else {
                     x02 = a;
                     y02 = b;
                  }
               } else {
                  nonex = a;
                  noney = b;
               }
            }
         }

         addmove(new Move(x01,y01,x02,y02,nonex,noney));
      }

      flip3(x,y);
   }

   public static void flip3(int x, int y){
      ArrayList<Integer> xs = new ArrayList<Integer>();
      ArrayList<Integer> ys = new ArrayList<Integer>();

      for(int a = x; a <= x+1; a++){
         for(int b = y; b <= y+1; b++){
            if(board[a][b] == 1){
               xs.add(a);
               ys.add(b);
            }
         }
      }

      addmove(new Move(xs.get(0),ys.get(0),xs.get(1),ys.get(1),xs.get(2),ys.get(2)));
   }

   public static void flip4(int x, int y){
      addmove(new Move(x,y,x+1,y,x,y+1));
      flip1(x,y);
   }

   public static class Move{
      int x1;
      int y1;
      int x2;
      int y2;
      int x3;
      int y3;

      public Move(int a, int b, int c, int d, int e, int f){
         x1 = a+1;
         y1 = b+1;
         x2 = c+1;
         y2 = d+1;
         x3 = e+1;
         y3 = f+1;
      }

      public String toString(){
         return x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3;
      }
   }

}


//make sure to make new file!
import java.io.*;
import java.util.*;

public class A684b{

   public static ArrayList<Move> answer;
   public static int n;
   public static int m;

   public static int[][] board;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      int t = Integer.parseInt(f.readLine());

      for(int q = 1; q <= t; q++){

         StringTokenizer st = new StringTokenizer(f.readLine());

         n = Integer.parseInt(st.nextToken());
         m = Integer.parseInt(st.nextToken());

         board = new int[n][m];
         for(int k = 0; k < n; k++){
            char[] c = f.readLine().toCharArray();
            for(int j = 0; j < m; j++){
               board[k][j] = Character.getNumericValue(c[j]);
            }
         }

         answer = new ArrayList<Move>();

         if(m%2 == 1){
            //make right column all 0
            for(int k = 0; k < n; k++){
               if(board[k][m-1] == 1){
                  if(k < n-1){
                     addmove(new Move(k,m-1,k,m-2,k+1,m-2));
                  } else {
                     addmove(new Move(k,m-1,k,m-2,k-1,m-2));
                  }
               }
            }
            m--;
         }

         for(int j = 0; j < m; j += 2){
            for(int k = 0; k < n-2; k++){
               if(board[k][j] == 1){
                  addmove(new Move(k,j,k+1,j,k+1,j+1));
               }
               if(board[k][j+1] == 1){
                  addmove(new Move(k,j+1,k+1,j+1,k+1,j));
               }
            }
            //last 2v2
            int num1 = 0;
            for(int a = n-2; a < n; a++){
               for(int b = j; b < j+2; b++){
                  if(board[a][b] == 1) num1++;
               }
            }

            if(num1 == 1) flip1(n-2,j);
            else if(num1 == 2) flip2(n-2,j);
            else if(num1 == 3) flip3(n-2,j);
            else if(num1 == 4) flip4(n-2,j);
         }

         out.println(answer.size());
         StringJoiner sj = new StringJoiner("\n");
         for(Move move : answer){
            sj.add(move.toString());
         }
         out.println(sj);

      }

      out.close();
   }

   public static void addmove(Move mv){
      board[mv.x1-1][mv.y1-1] ^= 1;
      board[mv.x2-1][mv.y2-1] ^= 1;
      board[mv.x3-1][mv.y3-1] ^= 1;
      answer.add(mv);
   }

   public static void flip1(int x, int y){
      if(board[x][y] == 1) fliptl(x,y);
      else if(board[x][y+1] == 1) fliptr(x,y+1);
      else if(board[x+1][y] == 1) flipbl(x+1,y);
      else flipbr(x+1,y+1);
   }

   public static void fliptl(int x, int y){
      addmove(new Move(x,y,x,y+1,x+1,y+1));
      addmove(new Move(x,y,x+1,y,x+1,y+1));
      addmove(new Move(x,y,x+1,y,x,y+1));
   }

   public static void fliptr(int x, int y){
      addmove(new Move(x,y,x,y-1,x+1,y-1));
      addmove(new Move(x,y,x+1,y,x+1,y-1));
      addmove(new Move(x,y,x+1,y,x,y-1));
   }

   public static void flipbl(int x, int y){
      addmove(new Move(x,y,x,y+1,x-1,y+1));
      addmove(new Move(x,y,x-1,y,x-1,y+1));
      addmove(new Move(x,y,x-1,y,x,y+1));
   }

   public static void flipbr(int x, int y){
      addmove(new Move(x,y,x,y-1,x-1,y-1));
      addmove(new Move(x,y,x-1,y,x-1,y-1));
      addmove(new Move(x,y,x-1,y,x,y-1));
   }

   public static void flip2(int x, int y){
      if(board[x][y] != board[x+1][y] && board[x][y] != board[x][y+1]){
         //diagonal
         if(board[x][y] == 1){
            addmove(new Move(x,y,x+1,y,x,y+1));
         } else {
            addmove(new Move(x,y+1,x,y,x+1,y+1));
         }
      } else {
         //2 in a row
         //pick a 0
         int x01 = -1;
         int y01 = -1;
         int x02 = -1;
         int y02 = -1;
         int nonex = -1;
         int noney = -1;
         for(int a = x; a <= x+1; a++){
            for(int b = y; b <= y+1; b++){
               if(board[a][b] == 0){
                  if(x01 == -1){
                     x01 = a;
                     y01 = b;
                  } else {
                     x02 = a;
                     y02 = b;
                  }
               } else {
                  nonex = a;
                  noney = b;
               }
            }
         }

         addmove(new Move(x01,y01,x02,y02,nonex,noney));
      }

      flip3(x,y);
   }

   public static void flip3(int x, int y){
      ArrayList<Integer> xs = new ArrayList<Integer>();
      ArrayList<Integer> ys = new ArrayList<Integer>();

      for(int a = x; a <= x+1; a++){
         for(int b = y; b <= y+1; b++){
            if(board[a][b] == 1){
               xs.add(a);
               ys.add(b);
            }
         }
      }

      addmove(new Move(xs.get(0),ys.get(0),xs.get(1),ys.get(1),xs.get(2),ys.get(2)));
   }

   public static void flip4(int x, int y){
      addmove(new Move(x,y,x+1,y,x,y+1));
      flip1(x,y);
   }

   public static class Move{
      int x1;
      int y1;
      int x2;
      int y2;
      int x3;
      int y3;

      public Move(int a, int b, int c, int d, int e, int f){
         x1 = a+1;
         y1 = b+1;
         x2 = c+1;
         y2 = d+1;
         x3 = e+1;
         y3 = f+1;
      }

      public String toString(){
         return x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3;
      }
   }

}


//make sure to make new file!
import java.io.*;
import java.util.*;

public class A684b{

   public static ArrayList<Move> answer;
   public static int n;
   public static int m;

   public static int[][] board;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      int t = Integer.parseInt(f.readLine());

      for(int q = 1; q <= t; q++){

         StringTokenizer st = new StringTokenizer(f.readLine());

         n = Integer.parseInt(st.nextToken());
         m = Integer.parseInt(st.nextToken());

         board = new int[n][m];
         for(int k = 0; k < n; k++){
            char[] c = f.readLine().toCharArray();
            for(int j = 0; j < m; j++){
               board[k][j] = Character.getNumericValue(c[j]);
            }
         }

         answer = new ArrayList<Move>();

         if(m%2 == 1){
            //make right column all 0
            for(int k = 0; k < n; k++){
               if(k < n-1){
                  addmove(new Move(k,m-1,k,m-2,k+1,m-2));
               } else {
                  addmove(new Move(k,m-1,k,m-2,k-1,m-2));
               }
            }
            m--;
         }

         for(int j = 0; j < m; j += 2){
            for(int k = 0; k < n-2; k++){
               if(board[k][j] == 1){
                  addmove(new Move(k,j,k+1,j,k+1,j+1));
               }
               if(board[k][j+1] == 1){
                  addmove(new Move(k,j+1,k+1,j+1,k+1,j));
               }
            }
            //last 2v2
            int num1 = 0;
            for(int a = n-2; a < n; a++){
               for(int b = j; b < j+2; b++){
                  if(board[a][b] == 1) num1++;
               }
            }

            if(num1 == 1) flip1(n-2,j);
            else if(num1 == 2) flip2(n-2,j);
            else if(num1 == 3) flip3(n-2,j);
            else if(num1 == 4) flip4(n-2,j);
         }

         out.println(answer.size());
         StringJoiner sj = new StringJoiner("\n");
         for(Move move : answer){
            sj.add(move.toString());
         }
         out.println(sj);

      }

      out.close();
   }

   public static void addmove(Move mv){
      board[mv.x1-1][mv.y1-1] ^= 1;
      board[mv.x2-1][mv.y2-1] ^= 1;
      board[mv.x3-1][mv.y3-1] ^= 1;
      answer.add(mv);
   }

   public static void flip1(int x, int y){
      if(board[x][y] == 1) fliptl(x,y);
      else if(board[x][y+1] == 1) fliptr(x,y);
      else if(board[x+1][y] == 1) flipbl(x,y);
      else flipbr(x,y);
   }

   public static void fliptl(int x, int y){
      answer.add(new Move(x,y,x,y+1,x+1,y+1));
      answer.add(new Move(x,y,x+1,y,x+1,y+1));
      answer.add(new Move(x,y,x+1,y,x,y+1));
   }

   public static void fliptr(int x, int y){
      answer.add(new Move(x,y,x,y-1,x+1,y-1));
      answer.add(new Move(x,y,x+1,y,x+1,y-1));
      answer.add(new Move(x,y,x+1,y,x,y-1));
   }

   public static void flipbl(int x, int y){
      answer.add(new Move(x,y,x,y+1,x-1,y+1));
      answer.add(new Move(x,y,x-1,y,x-1,y+1));
      answer.add(new Move(x,y,x-1,y,x,y+1));
   }

   public static void flipbr(int x, int y){
      answer.add(new Move(x,y,x,y-1,x-1,y-1));
      answer.add(new Move(x,y,x-1,y,x-1,y-1));
      answer.add(new Move(x,y,x-1,y,x,y-1));
   }

   public static void flip2(int x, int y){
      if(board[x][y] != board[x+1][y] && board[x][y] != board[x][y+1]){
         //diagonal
         if(board[x][y] == 1){
            addmove(new Move(x,y,x+1,y,x,y+1));
         } else {
            addmove(new Move(x,y+1,x,y,x+1,y+1));
         }
      } else {
         //2 in a row
         //pick a 0
         int x01 = -1;
         int y01 = -1;
         int x02 = -1;
         int y02 = -1;
         int nonex = -1;
         int noney = -1;
         for(int a = x; a <= x+1; a++){
            for(int b = y; b <= y+1; b++){
               if(board[a][b] == 0){
                  if(x01 == -1){
                     x01 = a;
                     y01 = b;
                  } else {
                     x02 = a;
                     y02 = b;
                  }
               } else {
                  nonex = a;
                  noney = b;
               }
            }
         }

         addmove(new Move(x01,y01,x02,y02,nonex,noney));
      }

      flip3(x,y);
   }

   public static void flip3(int x, int y){
      ArrayList<Integer> xs = new ArrayList<Integer>();
      ArrayList<Integer> ys = new ArrayList<Integer>();

      for(int a = x; a <= x+1; a++){
         for(int b = y; b <= y+1; b++){
            if(board[a][b] == 1){
               xs.add(a);
               ys.add(b);
            }
         }
      }

      addmove(new Move(xs.get(0),ys.get(0),xs.get(1),ys.get(1),xs.get(2),ys.get(2)));
   }

   public static void flip4(int x, int y){
      addmove(new Move(x,y,x+1,y,x,y+1));
      flip1(x,y);
   }

   public static class Move{
      int x1;
      int y1;
      int x2;
      int y2;
      int x3;
      int y3;

      public Move(int a, int b, int c, int d, int e, int f){
         x1 = a+1;
         y1 = b+1;
         x2 = c+1;
         y2 = d+1;
         x3 = e+1;
         y3 = f+1;
      }

      public String toString(){
         return x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3;
      }
   }

}


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    static List<int[]> ops = new ArrayList<>(100 * 100);
    static int[] op = new int[6];
    static int idx = 0;
    static int[][] DIR = new int[][] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 }, };

    static Boolean[][] grid;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while (t-- > 0) {
            ops.clear();

            int n = sc.nextInt();
            int m = sc.nextInt();
            grid = new Boolean[n][m];
            for (int i = 0; i < n; i++) {
                String row = sc.next();
                grid[i] = row.chars().mapToObj(ch -> ch == '1').toArray(Boolean[]::new);
            }

            for (int i = 0; i < n - 1; i++) {
                for (int j = 0; j < m - 1; j++) {
                    if (grid[i][j]) {
                        add(i, j);
                        add(i, j + 1);
                        add(i + 1, grid[i + 1][j] ? j : j + 1);
                    } else {
                        if (grid[i + 1][j]) {
                            add(i + 1, j);
                            add(i, j + 1);
                            add(i + 1, grid[i + 1][j] ? j : j + 1);
                        }
                    }
                }
                if (i < n - 2 && grid[i][m - 1]) {
                    add(i, m - 1);
                    add(i + 1, m - 2);
                    add(i + 1, m - 1);
                }
            }

            int i = grid.length - 2;
            int j = grid[0].length - 2;
            int ones;
            while ((ones = checkLast()) > 0) {
                int cnt = 0;
                switch (ones) {
                    case 1:
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (grid[r][c]) {
                                add(r, c);
                            }
                        }
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (!grid[r][c]) {
                                add(r, c);
                                if (++cnt == 2) {
                                    break;
                                }
                            }
                        }
                        break;
                    case 2:
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (!grid[r][c]) {
                                add(r, c);
                            }
                        }
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (grid[r][c]) {
                                add(r, c);
                                if (++cnt == 1) {
                                    break;
                                }
                            }
                        }
                        break;
                    case 3:
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (grid[r][c]) {
                                add(r, c);
                            }
                        }
                        break;
                    default:
                }
            }

            System.out.println(ops.size());
            StringBuilder buffer = new StringBuilder();
            for (int[] op : ops) {
                for (int id : op) {
                    buffer.append(id).append(" ");
                }
                buffer.append("\n");
            }
            System.out.println(buffer);
        }
    }

    static boolean add(int i, int j) {
        grid[i][j] = !grid[i][j];
        op[idx++] = i + 1;
        op[idx++] = j + 1;
        if (idx == 6) {
            ops.add(op);
            op = new int[6];
            idx = 0;
            return true;
        } else {
            return false;
        }
    }

    private static int checkLast() {
        int i = grid.length - 2;
        int j = grid[0].length - 2;
        int one = 0;
        for (int[] d : DIR) {
            if (grid[i + d[0]][j + d[1]]) {
                one++;
            }
        }
        return one;
    }

}


import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    static List<int[]> ops = new ArrayList<>(100 * 100);
    static int[] op = new int[6];
    static int idx = 0;
    static int[][] DIR = new int[][] { { 0, 0 }, { 0, 1 }, { 1, 0 }, { 1, 1 }, };

    static Boolean[][] grid;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while (t-- > 0) {
            ops.clear();

            int n = sc.nextInt();
            int m = sc.nextInt();
            grid = new Boolean[n][m];
            for (int i = 0; i < n; i++) {
                String row = sc.next();
                grid[i] = row.chars().mapToObj(ch -> ch == '1').toArray(Boolean[]::new);
            }

            for (int i = 0; i < n - 1; i++) {
                for (int j = 0; j < m - 1; j++) {
                    if (grid[i][j]) {
                        add(i, j);
                        add(i, j + 1);
                        add(i + 1, grid[i + 1][j] ? j : j + 1);
                    } else {
                        if (grid[i + 1][j]) {
                            add(i + 1, j);
                            add(i, j + 1);
                            add(i + 1, grid[i + 1][j] ? j : j + 1);
                        }
                    }
                }
                if (i < n - 2 && grid[i][m - 1]) {
                    add(i, m - 1);
                    add(i + 1, m - 2);
                    add(i + 1, m - 1);
                }
            }

            int i = grid.length - 2;
            int j = grid[0].length - 2;
            int ones;
            while ((ones = checkLast()) > 0) {
                int cnt = 0;
                switch (ones) {
                    case 1:
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (grid[r][c] || cnt++ < 2) {
                                add(r, c);
                            }
                        }
                        break;
                    case 2:
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (!grid[r][c] || cnt++ < 1) {
                                add(r, c);
                            }
                        }
                        break;
                    case 3:
                        for (int[] d : DIR) {
                            int r = i + d[0];
                            int c = j + d[1];
                            if (grid[r][c]) {
                                add(r, c);
                            }
                        }
                        break;
                    default:
                }
            }

            System.out.println(ops.size());
            StringBuilder buffer = new StringBuilder();
            for (int[] op : ops) {
                for (int id : op) {
                    buffer.append(id).append(" ");
                }
                buffer.append("\n");
            }
            System.out.println(buffer);
        }
    }

    static boolean add(int i, int j) {
        grid[i][j] = !grid[i][j];
        op[idx++] = i + 1;
        op[idx++] = j + 1;
        if (idx == 6) {
            ops.add(op);
            op = new int[6];
            idx = 0;
            return true;
        } else {
            return false;
        }
    }

    private static int checkLast() {
        int i = grid.length - 2;
        int j = grid[0].length - 2;
        int one = 0;
        for (int[] d : DIR) {
            if (grid[i + d[0]][j + d[1]]) {
                one++;
            }
        }
        return one;
    }

}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA2 solver = new TaskA2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA2 {
        int height;
        int width;
        int[][] a;
        List<String> ans = new ArrayList<>();

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int numTests = in.nextInt();
            for (int test = 0; test < numTests; test++) {
                height = in.nextInt();
                width = in.nextInt();
                a = new int[height][width];
                for (int r = 0; r < height; r++) {
                    char[] s = in.next().toCharArray();
                    for (int c = 0; c < width; c++) {
                        a[r][c] = s[c] - '0';
                    }
                }
                ans.clear();
                for (int r = height - 1; r >= 0; r--) {
                    for (int c = width - 1; c >= 0; c--) {
                        if (r < 2 && c < 2) {
                            continue;
                        }
                        if (a[r][c] == 0) {
                            continue;
                        }
                        if (r > 0) {
                            flip(r * width + c, (r - 1) * width + c, r * width + (c - 1));
                        } else {
                            flip(r * width + c, (r + 1) * width + (c - 1), r * width + (c - 1));
                        }
                    }
                }
                List<Integer> ones = new ArrayList<>();
                List<Integer> zeros = new ArrayList<>();
                for (int r = 0; r < 2; r++) {
                    for (int c = 0; c < 2; c++) {
                        int x = r * width + c;
                        if (a[r][c] == 1) {
                            ones.add(x);
                        } else {
                            zeros.add(x);
                        }
                    }
                }
                switch (ones.size()) {
                    case 0:
                        break;
                    case 1:
                        solveOne(ones.get(0), zeros.get(0), zeros.get(1), zeros.get(2));
                        break;
                    case 2:
                        flip(ones.get(0), zeros.get(0), zeros.get(1));
                        solveOne(ones.get(1), ones.get(0), zeros.get(0), zeros.get(1));
                        break;
                    case 3:
                        flip(ones.get(0), ones.get(1), ones.get(2));
                        break;
                    case 4:
                        flip(ones.get(0), ones.get(1), ones.get(2));
                        solveOne(ones.get(3), ones.get(0), ones.get(1), ones.get(2));
                        break;
                }
                out.println(ans.size());
                for (String s : ans) {
                    out.println(s);
                }
            }
        }

        private void flip(int x, int y, int z) {
            int rx = x / width;
            int cx = x % width;
            int ry = y / width;
            int cy = y % width;
            int rz = z / width;
            int cz = z % width;
            a[rx][cx] ^= 1;
            a[ry][cy] ^= 1;
            a[rz][cz] ^= 1;
            ans.add(String.format("%d %d %d %d %d %d", rx + 1, cx + 1, ry + 1, cy + 1, rz + 1, cz + 1));
        }

        private void solveOne(int one, int z0, int z1, int z2) {
            flip(one, z0, z1);
            flip(one, z1, z2);
            flip(one, z2, z0);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA2 solver = new TaskA2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA2 {
        int height;
        int width;
        int[][] a;
        List<String> ans = new ArrayList<>();

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int numTests = in.nextInt();
            for (int test = 0; test < numTests; test++) {
                height = in.nextInt();
                width = in.nextInt();
                a = new int[height][width];
                for (int r = 0; r < height; r++) {
                    char[] s = in.next().toCharArray();
                    for (int c = 0; c < width; c++) {
                        a[r][c] = s[c] - '0';
                    }
                }
                ans.clear();
                for (int r = 0; r + 1 < height; r++) {
                    for (int c = 0; c + 1 < width; c++) {
                        List<Integer> ones = new ArrayList<>();
                        List<Integer> zeros = new ArrayList<>();
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                int x = (r + i) * width + (c + j);
                                if (a[r + i][c + j] == 1) {
                                    ones.add(x);
                                } else {
                                    zeros.add(x);
                                }
                            }
                        }
                        if (ones.size() >= 3) {
                            flip(ones.get(0), ones.get(1), ones.get(2));
                        } else if (ones.size() == 2) {
                            flip(ones.get(0), ones.get(1), zeros.get(zeros.size() - 1));
                        }
                    }
                }
                for (int r = 0; r + 1 < height; r++) {
                    for (int c = 0; c + 1 < width; c++) {
                        List<Integer> ones = new ArrayList<>();
                        List<Integer> zeros = new ArrayList<>();
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                int x = (r + i) * width + (c + j);
                                if (a[r + i][c + j] == 1) {
                                    ones.add(x);
                                } else {
                                    zeros.add(x);
                                }
                            }
                        }
                        if (ones.size() > 1) {
                            throw new AssertionError();
                        }
                        if (ones.isEmpty()) {
                            continue;
                        }
                        solveOne(ones.get(0), zeros.get(0), zeros.get(1), zeros.get(2));
                    }
                }
                out.println(ans.size());
                for (String s : ans) {
                    out.println(s);
                }
            }
        }

        private void flip(int x, int y, int z) {
            int rx = x / width;
            int cx = x % width;
            int ry = y / width;
            int cy = y % width;
            int rz = z / width;
            int cz = z % width;
            a[rx][cx] ^= 1;
            a[ry][cy] ^= 1;
            a[rz][cz] ^= 1;
            ans.add(String.format("%d %d %d %d %d %d", rx + 1, cx + 1, ry + 1, cy + 1, rz + 1, cz + 1));
        }

        private void solveOne(int one, int z0, int z1, int z2) {
            flip(one, z0, z1);
            flip(one, z1, z2);
            flip(one, z2, z0);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA2 solver = new TaskA2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA2 {
        int height;
        int width;
        int[][] a;
        List<String> ans = new ArrayList<>();

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int numTests = in.nextInt();
            for (int test = 0; test < numTests; test++) {
                height = in.nextInt();
                width = in.nextInt();
                a = new int[height][width];
                for (int r = 0; r < height; r++) {
                    char[] s = in.next().toCharArray();
                    for (int c = 0; c < width; c++) {
                        a[r][c] = s[c] - '0';
                    }
                }
                ans.clear();
                for (int r = height - 1; r >= 2; r--) {
                    for (int c = width - 1; c >= 0; c--) {
                        if (a[r][c] == 1) {
                            flip(r * width + c, (r - 1) * width + c, (r - 1) * width + (c == 0 ? c + 1 : c - 1));
                        }
                    }
                }
                for (int c = width - 1; c >= 2; c--) {
                    if (a[0][c] == 1 && a[1][c] == 1) {
                        flip(0 * width + c, 1 * width + c, 0 * width + (c - 1));
                    } else if (a[0][c] == 1) {
                        flip(0 * width + c, 0 * width + (c - 1), 1 * width + (c - 1));
                    } else if (a[1][c] == 1) {
                        flip(1 * width + c, 0 * width + (c - 1), 1 * width + (c - 1));
                    }
                }
                List<Integer> ones = new ArrayList<>();
                List<Integer> zeros = new ArrayList<>();
                for (int r = 0; r < 2; r++) {
                    for (int c = 0; c < 2; c++) {
                        int x = r * width + c;
                        if (a[r][c] == 1) {
                            ones.add(x);
                        } else {
                            zeros.add(x);
                        }
                    }
                }
                switch (ones.size()) {
                    case 0:
                        break;
                    case 1:
                        solveOne(ones.get(0), zeros.get(0), zeros.get(1), zeros.get(2));
                        break;
                    case 2:
                        flip(ones.get(0), zeros.get(0), zeros.get(1));
                        solveOne(ones.get(1), ones.get(0), zeros.get(0), zeros.get(1));
                        break;
                    case 3:
                        flip(ones.get(0), ones.get(1), ones.get(2));
                        break;
                    case 4:
                        flip(ones.get(0), ones.get(1), ones.get(2));
                        solveOne(ones.get(3), ones.get(0), ones.get(1), ones.get(2));
                        break;
                }
                out.println(ans.size());
                for (String s : ans) {
                    out.println(s);
                }
            }
        }

        private void flip(int x, int y, int z) {
            int rx = x / width;
            int cx = x % width;
            int ry = y / width;
            int cy = y % width;
            int rz = z / width;
            int cz = z % width;
            a[rx][cx] ^= 1;
            a[ry][cy] ^= 1;
            a[rz][cz] ^= 1;
            ans.add(String.format("%d %d %d %d %d %d", rx + 1, cx + 1, ry + 1, cy + 1, rz + 1, cz + 1));
        }

        private void solveOne(int one, int z0, int z1, int z2) {
            flip(one, z0, z1);
            flip(one, z1, z2);
            flip(one, z2, z0);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA2 solver = new TaskA2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA2 {
        int height;
        int width;
        int[][] a;
        List<String> ans = new ArrayList<>();

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int numTests = in.nextInt();
            for (int test = 0; test < numTests; test++) {
                height = in.nextInt();
                width = in.nextInt();
                a = new int[height][width];
                for (int r = 0; r < height; r++) {
                    char[] s = in.next().toCharArray();
                    for (int c = 0; c < width; c++) {
                        a[r][c] = s[c] - '0';
                    }
                }
                ans.clear();
                for (int r = 0; r + 1 < height; r++) {
                    for (int c = 0; c + 1 < width; c++) {
                        List<Integer> ones = new ArrayList<>();
                        List<Integer> zeros = new ArrayList<>();
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                int x = (r + i) * width + (c + j);
                                if (a[r + i][c + j] == 1) {
                                    ones.add(x);
                                } else {
                                    zeros.add(x);
                                }
                            }
                        }
                        if (ones.size() >= 3) {
                            flip(ones.get(0), ones.get(1), ones.get(2));
                        } else if (ones.size() == 2) {
                            int z = zeros.get(0);
                            flip(ones.get(0), ones.get(1), z);
                            solveOne(z, ones.get(0), ones.get(1), zeros.get(1));
                        }
                    }
                }
                for (int r = 0; r + 1 < height; r++) {
                    for (int c = 0; c + 1 < width; c++) {
                        List<Integer> ones = new ArrayList<>();
                        List<Integer> zeros = new ArrayList<>();
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                int x = (r + i) * width + (c + j);
                                if (a[r + i][c + j] == 1) {
                                    ones.add(x);
                                } else {
                                    zeros.add(x);
                                }
                            }
                        }
                        if (ones.size() > 1) {
                            throw new AssertionError();
                        }
                        if (ones.isEmpty()) {
                            continue;
                        }
                        solveOne(ones.get(0), zeros.get(0), zeros.get(1), zeros.get(2));
                    }
                }
                out.println(ans.size());
                for (String s : ans) {
                    out.println(s);
                }
            }
        }

        private void flip(int x, int y, int z) {
            int rx = x / width;
            int cx = x % width;
            int ry = y / width;
            int cy = y % width;
            int rz = z / width;
            int cz = z % width;
            a[rx][cx] ^= 1;
            a[ry][cy] ^= 1;
            a[rz][cz] ^= 1;
            ans.add(String.format("%d %d %d %d %d %d", rx + 1, cx + 1, ry + 1, cy + 1, rz + 1, cz + 1));
        }

        private void solveOne(int one, int z0, int z1, int z2) {
            flip(one, z0, z1);
            flip(one, z1, z2);
            flip(one, z2, z0);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA2 solver = new TaskA2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA2 {
        int height;
        int width;
        int[][] a;
        List<String> ans = new ArrayList<>();

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int numTests = in.nextInt();
            for (int test = 0; test < numTests; test++) {
                height = in.nextInt();
                width = in.nextInt();
                a = new int[height][width];
                for (int r = 0; r < height; r++) {
                    char[] s = in.next().toCharArray();
                    for (int c = 0; c < width; c++) {
                        a[r][c] = s[c] - '0';
                    }
                }
                ans.clear();
                for (int r = height - 1; r >= 2; r--) {
                    for (int c = width - 1; c >= 0; c--) {
                        if (a[r][c] == 1) {
                            flip(r * width + c, (r - 1) * width + c, (r - 1) * width + (c == 0 ? c + 1 : c - 1));
                        }
                    }
                }
                for (int c = width - 1; c >= 2; c--) {
                    if (a[0][c] == 1 && a[1][c] == 1) {
                        flip(0 * width + c, 1 * width + c, 0 * width + (c - 1));
                    } else if (a[0][c] == 1) {
                        flip(0 * width + c, 0 * width + (c - 1), 1 * width + (c - 1));
                    } else if (a[1][c] == 1) {
                        flip(1 * width + c, 0 * width + (c - 1), 1 * width + (c - 1));
                    }
                }
                List<Integer> ones = new ArrayList<>();
                List<Integer> zeros = new ArrayList<>();
                for (int r = 0; r < 2; r++) {
                    for (int c = 0; c < 2; c++) {
                        int x = r * width + c;
                        if (a[r][c] == 1) {
                            ones.add(x);
                        } else {
                            zeros.add(x);
                        }
                    }
                }
                switch (ones.size()) {
                    case 0:
                        break;
                    case 1:
                        solveOne(ones.get(0), zeros.get(0), zeros.get(1), zeros.get(2));
                        break;
                    case 2:
                        flip(ones.get(0), ones.get(1), zeros.get(0));
                        solveOne(zeros.get(0), ones.get(0), ones.get(1), zeros.get(1));
                        break;
                    case 3:
                        flip(ones.get(0), ones.get(1), ones.get(2));
                        break;
                    case 4:
                        flip(ones.get(0), ones.get(1), ones.get(2));
                        solveOne(ones.get(3), ones.get(0), ones.get(1), ones.get(2));
                        break;
                }
                out.println(ans.size());
                for (String s : ans) {
                    out.println(s);
                }
            }
        }

        private void flip(int x, int y, int z) {
            int rx = x / width;
            int cx = x % width;
            int ry = y / width;
            int cy = y % width;
            int rz = z / width;
            int cz = z % width;
            a[rx][cx] ^= 1;
            a[ry][cy] ^= 1;
            a[rz][cz] ^= 1;
            ans.add(String.format("%d %d %d %d %d %d", rx + 1, cx + 1, ry + 1, cy + 1, rz + 1, cz + 1));
        }

        private void solveOne(int one, int z0, int z1, int z2) {
            flip(one, z0, z1);
            flip(one, z1, z2);
            flip(one, z2, z0);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.List;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA2 solver = new TaskA2();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA2 {
        int height;
        int width;
        int[][] a;
        List<String> ans = new ArrayList<>();

        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int numTests = in.nextInt();
            for (int test = 0; test < numTests; test++) {
                height = in.nextInt();
                width = in.nextInt();
                a = new int[height][width];
                for (int r = 0; r < height; r++) {
                    char[] s = in.next().toCharArray();
                    for (int c = 0; c < width; c++) {
                        a[r][c] = s[c] - '0';
                    }
                }
                ans.clear();
                while (true) {
                    boolean any = false;
                    for (int r = 0; r + 1 < height; r++) {
                        for (int c = 0; c + 1 < width; c++) {
                            List<Integer> ones = new ArrayList<>();
                            List<Integer> zeros = new ArrayList<>();
                            for (int i = 0; i < 2; i++) {
                                for (int j = 0; j < 2; j++) {
                                    int x = (r + i) * width + (c + j);
                                    if (a[r + i][c + j] == 1) {
                                        ones.add(x);
                                    } else {
                                        zeros.add(x);
                                    }
                                }
                            }
                            if (ones.size() > 1) {
                                any = true;
                            }
                            if (ones.size() >= 3) {
                                flip(ones.get(0), ones.get(1), ones.get(2));
                            } else if (ones.size() == 2) {
                                flip(ones.get(0), ones.get(1), zeros.get(0));
                            }
                        }
                    }
                    if (!any) {
                        break;
                    }
                }
                for (int r = 0; r + 1 < height; r++) {
                    for (int c = 0; c + 1 < width; c++) {
                        List<Integer> ones = new ArrayList<>();
                        List<Integer> zeros = new ArrayList<>();
                        for (int i = 0; i < 2; i++) {
                            for (int j = 0; j < 2; j++) {
                                int x = (r + i) * width + (c + j);
                                if (a[r + i][c + j] == 1) {
                                    ones.add(x);
                                } else {
                                    zeros.add(x);
                                }
                            }
                        }
                        if (ones.size() > 1) {
                            throw new AssertionError();
                        }
                        if (ones.isEmpty()) {
                            continue;
                        }
                        solveOne(ones.get(0), zeros.get(0), zeros.get(1), zeros.get(2));
                    }
                }
                out.println(ans.size());
                for (String s : ans) {
                    out.println(s);
                }
            }
        }

        private void flip(int x, int y, int z) {
            int rx = x / width;
            int cx = x % width;
            int ry = y / width;
            int cy = y % width;
            int rz = z / width;
            int cz = z % width;
            a[rx][cx] ^= 1;
            a[ry][cy] ^= 1;
            a[rz][cz] ^= 1;
            ans.add(String.format("%d %d %d %d %d %d", rx + 1, cx + 1, ry + 1, cy + 1, rz + 1, cz + 1));
        }

        private void solveOne(int one, int z0, int z1, int z2) {
            flip(one, z0, z1);
            flip(one, z1, z2);
            flip(one, z2, z0);
        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

    }
}